🔗 Connect to your data and build better dashboards with Plotly and Claude. Reserve your spot.

author photo

Nathan Drezner

March 13, 2026

Plotly Dash Embedded: Build Data Apps, Deploy Anywhere

Deploying a data app to multiple platforms typically means maintaining separate codebases.

Each deployment context (for example: Salesforce, customer portals, partner sites) requires its own authentication implementation, CORS configuration, and integration logic. The maintenance cost scales linearly with the number of deployment targets.

Dash Embedded eases the challenge. This Python plugin allows a single Dash application to run standalone or embed across different domains with one line of configuration. The same codebase handles authentication, cross-domain communication, and state synchronization regardless of where it's deployed.

What is Dash Embedded?

Package within Plotly Dash Enterprise, Dash Embedded is a Python plugin that gives your Dash applications superpowers. With a single line of code, your data app can run as a standalone application or embed seamlessly into parent applications across different domains. This way, you can use the same codebase and logic across multiple deployment contexts.

import dash_embedded
app = Dash(__name__,
plugins=[dash_embedded.Embeddable(origins=['https://your-domain.com'])])

With one import, one plugin parameter, your Dash app is now embeddable without a separate build process.

The embedded analytics problem

Dash Embedded handles all the technical challenges people commonly face when implementing embedded analytics. Behind the scenes, embedding analytics requires managing CORS headers, providing authentication wrappers, enabling bidirectional communication, and generally doing the tedious infrastructure work.

Here are just some of the many, many challenges embedding analytics involves when you do it the hard way:

Cross-origin resource sharing (CORS): The browser security model that protects users from malicious sites also really, really doesn't want your data app talking to a parent application on a different domain. Configuring CORS correctly is an art form, and getting it wrong means your app either doesn't work or is insecure. Pick your poison.

Authentication across boundaries: Your embedded dashboard needs to know who's using it, but the user already authenticated with the parent application. Do you make them log in again? Pass tokens through URL parameters? (Please don't.) Implement a complex OAuth dance? Every option has tradeoffs, and most of them involve more code than you wanted to write.

State synchronization: The parent app knows which customer the user selected. Your embedded dashboard needs that information too. Now you're passing messages between iframes, managing event listeners, and weighing race conditions.

Iframe security: Modern browsers have strong opinions about what iframes can and can't do. Navigating these restrictions while maintaining functionality requires very specific expertise.

How Dash Embedded solves the embedded analytics problem

Seamless cross-domain integration

Remember those CORS errors I mentioned? Dash Embedded solves them!

The Embeddable plugin automatically configures Flask-CORS for your application, handling the preflight requests, header management, and origin validation that make cross-domain embedding possible. When you specify which domains are allowed to embed your app, Dash Embedded handles the rest.

# Allow specific domains
plugins=[dash_embedded.Embeddable(origins=['https://app.yourcompany.com', 'https://portal.partner.com'])]
# Or allow everything (for development—please don't do this in production)
plugins=[dash_embedded.Embeddable(origins=['*'])]

Enterprise-grade authentication

Different deployment contexts require different security approaches. Dash Embedded provides two battle-tested authentication options:

JWT authentication (EmbeddedAuth)

JSON Web Tokens are the industry standard for stateless authentication, and Dash Embedded's JWT implementation is comprehensive:

  • Configurable algorithms (HS512 by default, because security matters)
  • Claims validation for audience, issuer, and custom fields
  • Automatic token refresh handling
  • Route protection with configurable ignore patterns
  • Integration with snapshot and PDF generation services
from dash_embedded import EmbeddedAuth
auth = EmbeddedAuth(
    app,
    secret='your-secret-key',
    audience='your-app',
    algorithms=['HS512']
)

Salesforce integration (SalesforceAuth)

If you're embedding into Salesforce, we've built specialized support for Canvas apps and embedded experiences:

  • HMAC-SHA256 request signature validation
  • Secure session management with properly configured cookies
  • Support for partitioned cookies (more on this shortly)
  • User context extraction from Salesforce signed requests
  • SameSite cookie handling that actually works across domains

Salesforce integration can be notoriously finicky. We've absorbed that pain so you don't have to.

Reactive state sharing with ConsumerContext

Your embedded data app operates within a parent application that maintains its own distinct state, encompassing the user’s selected customer, their active date range, and their specific preferences and permissions.

The ConsumerContext component creates a reactive bridge between your Dash data app and the parent application's state:

from dash_embedded import ConsumerContext
app.layout = html.Div([
    ConsumerContext(id='parent-context', path='selectedCustomer'),
    dcc.Graph(id='customer-chart')
])
@app.callback(
    Output('customer-chart', 'figure'),
    Input('parent-context', 'data')
)
def update_chart(customer_id):
    # This callback fires automatically when the parent app's
    # selectedCustomer changes. No polling. No manual refresh.
    return generate_chart_for_customer(customer_id)

When the parent application updates its state, your embedded dashboard reacts immediately. It's the kind of seamless integration that makes users think, "Wow, this all feels like one application." Because, in a sense, it is.

Calling parent functions with ConsumerFunction

Sometimes the data flows the other way. Your embedded dashboard has a "Save Report" button, and clicking it should trigger an action in the parent application. Or you want to navigate the user to a different page, or log an event in the parent's analytics system.

The ConsumerFunction component makes it possible:

from dash_embedded import ConsumerFunction
app.layout = html.Div([
    ConsumerFunction(id='save-to-parent', function='saveReport'),
    html.Button('Save Report', id='save-button'),
    html.Div(id='save-result')
])
@app.callback(
    Output('save-to-parent', 'args'),
    Input('save-button', 'n_clicks'),
    State('report-data', 'data'),
    prevent_initial_call=True
)
def trigger_save(n_clicks, report_data):
    return [report_data]  # Arguments passed to parent's saveReport function
@app.callback(
    Output('save-result', 'children'),
    Input('save-to-parent', 'result')
)
def show_result(result):
    return f"Saved successfully: {result}"

Your Dash app calls a function defined in the parent application and receives the result: two applications, working together as one.

What’s new: Recent updates

We've been busy making Dash Embedded even better. Here's what's landed recently:

Full Dash 3.0 compatibility (v3.0.0 and v3.0.1)

Dash 3.0 brought significant improvements to the framework, and Dash Embedded now fully supports it. Whether you're using the new features in Dash 3 or upgrading existing applications, your embedded deployments will work seamlessly.

The latest v3.0.1 release also cleaned up some internal housekeeping, specifically replacing deprecated pkg_resourcesimports with modern alternatives. It's the kind of tedious maintenance work that keeps everything running smoothly.

Fixed dynamic callbacks in embedded mode (v2.18.2)

If you've ever built a Dash app that generates callbacks programmatically, you know how powerful (and occasionally finicky) dynamic callbacks can be. Version 2.18.2 resolved issues where dynamic callback registration wasn't working correctly in embedded contexts. Your pattern-matching callbacks and dynamically generated components now behave identically whether the app runs standalone or embedded.

Partitioned cookie support (v2.14.0)

Chrome's Privacy Sandbox initiative is changing how cookies work across domains. The CHIPS (Cookies Having Independent Partitioned State) specification requires cookies to be partitioned when used in cross-site contexts.

Translation: If your embedded dashboard uses session cookies, and you want it to work in Chrome, you need partitioned cookie support. We've implemented it, so your Salesforce integrations and cross-domain embeddings will continue working as browsers tighten their privacy restrictions.

Improved error handling and logging

When something goes wrong in an embedded context, debugging can be challenging. Recent versions include better exception handling and more informative logging, making it easier to diagnose issues in production deployments.

Real-world use cases

Customer-facing analytics

You've built an amazing analytics platform. Now your customers want self-service access to their data, but they don't want to leave your application to get it.

Embed your Dash dashboards directly into your product. Customers see their analytics within the context of your application, with seamless authentication and real-time data. No separate login or jarring context switch.

Salesforce Canvas applications

Salesforce dominates enterprise CRM, which means your stakeholders likely want analytics inside Salesforce. Dash Embedded's SalesforceAuth makes this straightforward:

  • Deploy your Dash app as a Canvas component
  • Authenticate users via Salesforce's signed request mechanism
  • Access Salesforce user context and permissions
  • Let sales teams see Python-powered analytics without leaving their CRM

It's Python analytics meeting enterprise CRM, and they get along surprisingly well.

Internal tool consolidation

Most organizations have a sprawl of internal tools such as HR portals, IT dashboards, project management systems. Each tool could benefit from better analytics, but building separate dashboards for each is impractical.

With Dash Embedded, you can build your analytics once and embed them everywhere. The employee metrics dashboard works in the HR portal and the executive reporting system, infrastructure monitoring tools embed in both the IT dashboard and the incident management platform.

Partner and white-label solutions

If you provide analytics to partners or offer white-label solutions, Dash Embedded enables clean integration without exposing your underlying infrastructure. Partners embed your dashboards into their own applications, and you maintain full control over the analytics logic while they control the user experience.

Getting started with Dash Embedded

Ready to stop maintaining multiple dashboard codebases? Here's how to begin:

Installation

pip install dash-embedded --extra-index-url=... # You'll need to reference your Enterprise package index URL to install

Basic embedding

from dash import Dash, html, dcc
import dash_embedded
app = Dash(__name__, plugins=[dash_embedded.Embeddable(origins=['*'])])
app.layout = html.Div([
    html.H1('My Embeddable Dashboard'),
    dcc.Graph(id='my-chart', figure=create_figure())
])
if __name__  '__main__':
    app.run_server(debug=True)

Adding JWT authentication

from dash import Dash
import dash_embedded
from dash_embedded import EmbeddedAuth
app = Dash(__name__, plugins=[dash_embedded.Embeddable(origins=['https://parent-app.com'])])
auth = EmbeddedAuth(
    app,
    secret='your-secure-secret',  # Use environment variables in production!
    audience='your-dashboard',
    algorithms=['HS512']
)
# Your app is now protected. Only requests with valid JWTs will succeed.

Salesforce integration

from dash import Dash
import dash_embedded
from dash_embedded import SalesforceAuth
app = Dash(__name__, plugins=[dash_embedded.Embeddable(origins=['https://*.salesforce.com'])])
sf_auth = SalesforceAuth(
    app,
    consumer_secret='your-salesforce-consumer-secret'
)
# Your app now validates Salesforce signed requests automatically.

Production considerations

Before you deploy, a few important notes:

Specify allowed origins: That origins=['*'] is convenient for development, but in production, ensure to explicitly list the domains that should be able to embed your app. Security matters.

Secure your secrets: JWT secrets and Salesforce consumer secrets should come from environment variables or a secrets manager, never hardcoded in your source code.

Plan for scale: Embedded dashboards can see significant traffic, especially in customer-facing deployments. Make sure your infrastructure is ready.

Test cross-browser: Different browsers implement security policies differently. Test your embedded dashboards in Chrome, Firefox, Safari, and Edge before going live.

Building great analytics is hard enough without worrying about deployment infrastructure. Dash Embedded frees you up to focus on insights, visualizations, and user experience, while handling the complex plumbing of cross-domain embedding, authentication, and state management for you.

Build once, deploy anywhere.

Bluesky icon
X icon
Instagram icon
Youtube icon
Medium icon
Facebook icon

Product

© 2026
Plotly. All rights reserved.
Cookie Preferences