Developer's Guide to Cookieless Embedding
This guide is designed to walk you through Looker's Cookieless Embed logic, the "gotchas," and the architecture without getting bogged down in code syntax. You can find the nitty-gritty details in Looker's official documentation and in the package. If you would like lkr.dev to work on a code sample in your backend or frontend of choice, feel free to reach out here.
Stop. Do you think you really need this?
Before we dive in, let’s make sure you aren't over-engineering. Cookieless embedding is robust, but it requires significantly more development effort (backend API endpoints, token management, caching) than the standard method.
You should stick to Standard Signed Embedding with a Custom Domain if:
- You control the domain where Looker is embedded (e.g., your portal is portal.mycompany.com). And...
- You can set up a custom domain (e.g., analytics.mycompany.com) on Looker Core or by reaching out to your Account Manager for Looker hosted.
Why? If the top-level domains match (both end in mycompany.com), browsers treat Looker's cookies as "first-party." They won't get blocked, and you don't need to build complex token management.
You absolutely need Cookieless Embedding if:
Your embedding application is hosted across multiple, disparate domains that you do not fully control (e.g., a SaaS product with customer-a.com and customer-b.com domains), making a custom Looker domain impractical.
Important Links
Before you begin, you should familiarize yourself with the following links:
- Looker's Cookieless Embedding Documentation
- Looker's Embed SDK Documentation
- Create Acquire Cookieless Embed Session API
- Embedded Domain Allowlist
Test first with the demo application
Before you start building your own Looker embed, we strongly recommend running the Looker Embed SDK Demo Application. It’s the fastest way to verify that your Looker instance is correctly configured for cookieless embedding. We recommend getting at least one dashboard up and running with the following steps.
Step 1 - Enable Cookieless Embedding in your Looker instance
Navigate to Admin > Platform > Embed on your Looker instance. This requires Admin privileges.
- Enable Cookieless Embed: Toggle this setting to On.
- Embed SSO Authentication: Ensure this is also enabled if you plan to use signed features.
- Embedded Domain Allowlist: The demo server runs by default at
http://localhost:8080. Add this address to the allowlist to enable the demo to receive messages from Looker.
Step 2 - Customize the Demo Settings
The embed demo environment is configured using a .env file in the root of the repository. Create this file and add the following cookieless-specific configuration:
# Looker Instance Configuration
LOOKER_WEB_URL=mycompany.looker.com
LOOKER_API_URL=https://mycompany.looker.com
# API Credentials (from Admin > Users > API3 Keys)
LOOKER_CLIENT_ID=your_client_id
LOOKER_CLIENT_SECRET=your_client_secret
# Embed Configuration
LOOKER_EMBED_TYPE=cookieless
LOOKER_DASHBOARD_ID=123
Next, customize the embedded user's identity and permissions by editing demo/demo_user.json. This file defines the profile Looker will use for the cookieless session. Key fields include:
external_user_id: A unique ID for the user in your system.permissions: Roles likeaccess_data,see_looks,explore,see_user_dashboards,see_lookml_dashboards.models: The LookML models this user is allowed to access.
Step 3 - Build and Run
Clone the repo and run the following commands from the top-level embed-sdk directory:
npm install
npm run server
The server will listen on http://localhost:8080.
Step 4 - Verify in the UI
Once the app is running:
- Open your browser to
http://localhost:8080. - Ensure the "Use cookieless" radio button is selected.
- Click "Run".
This will initiate the cookieless handshake and load the Looker content into the iframe. Success here confirms your Looker instance permissions and domain allowlists are correctly configured! Now you should start integrating it into your own application.
The Tokens
Looker uses a number of client safe and client secret tokens to authenticate cookieless embedding. The importance of each token is described below, however ignorance is bliss. You can get away with not understanding the tokens and still have a successful implementation, but it's good to know what's happening under the hood when you get stuck. When implementing cookieless embedding, we strongly recommend using the @looker/embed-sdk to handle the most of the token management for you on the client.
Understanding the Tokens
The token handshake is the core of the cookieless embedding process. It's the mechanism that enables the embedding application to authenticate with Looker and obtain a token to access the Looker API.
The token handshake is a two-step process:
- The embedding application requests a token from the Looker API.
- The Looker API returns a token to the embedding application.
The token handshake is a secure process that uses a shared secret to authenticate the embedding application with Looker.
The Session Reference Token
This is the most critical piece of the puzzle. Think of the Session Reference Token exactly like a Refresh Token in OAuth/JWT flows. It is a Secret. If someone gets this token, they are that user. They can generate new sessions and access data as that user. Treat it as a secret and avoid sending it to the client (browser). In most scenarios, the client (browser) doesn't need it and your backend should receive it from Looker, store it securely, and use it only to communicate with the Looker server via server-to-server.
There are exceptions for sending it to the client, for example if you are avoiding storing in your backend. If so it's a secret and you will need to re-use it, therefore encrypt it before sending it to the client.
Its expiration is controlled by the session_length parameter in the acquire_embed_cookieless_session API call, which defaults to 5 minutes and can be set to a maximum of 30 days.
All Token Descriptions
| Token Type | Description |
|---|---|
| Session Reference Token | This is the most critical piece of the puzzle. Think of it exactly like a Refresh Token in OAuth/JWT flows. It is a Secret. If someone gets this token, they are that user. They can generate new sessions and access data as that user. Treat it as a secret and avoid sending it to the client (browser). In most scenarios, the client (browser) doesn't need it and your backend should receive it from Looker, store it securely, and use it only to communicate with the Looker server via server-to-server. Its expiration is controlled by the session_length parameter in the acquire_embed_cookieless_session API call, which defaults to 5 minutes and can be set to a maximum of 30 days. |
| Navigation Token | Add this to the iframe URL. It allows the user to load pages and click links within Looker. These are short-lived (typically 10 minutes or less), which limits the blast radius if intercepted. |
| API Token | The Looker Embed SDK uses this to fetch chart data. These are short-lived (typically 10 minutes or less), which limits the blast radius if intercepted. |
| Authentication Token | A one-time-use token (valid for only 30 seconds) used strictly to start the session. These are short-lived (typically 10 minutes or less), which limits the blast radius if intercepted. |
Don't forget your user agent.
The User Agent is a critical component of session security when using Looker's cookieless embed. Please ensure it is transmitted correctly from your browser to your backend and then to the Looker API. The user agent is used to match the browser iframe URL to the session reference token. If the user agent is not passed correctly, the iframe will not load. Cookieless Embedding Troubleshooting for more information on how to determine whether this is the issue with your embedding