Content Security Policy (CSP) is a layer of security created by the owners of a web application.
An effective (strict) CSP restricts which resources are allowed to a small set of domains. This has the potential to impact Pendo by preventing Pendo from loading or operating correctly. For example, the agent might not be called or guides might not load. For this reason, you might need to make an adjustment to your CSP to allow Pendo full functionality.
This article outlines the minimum required directives in your CSP to allow Pendo to have full functionality. If you're using Feedback, see Feedback's Content Security Policy.
CSP Overview
CSP is a method of specifying domains from which specific types of content in your web application can be loaded. A CSP can specify sources that are allowed for specific types of content, such as JavaScript, CSS, and images.
CSP is often used to prevent Cross Site Scripting (XSS) and data injection attacks, especially if you manage sensitive data. You might also use CSP if you want to:
- Ensure that page resources, such as images and frames, are only loaded from trusted sources.
- Prevent your application from being framed by untrusted domains.
- Transparently upgrade all resource requests to HTTPS.
You enable CSP by setting the Content-Security-Policy
HTTP response header or as a meta
tag on the main document. For example, an application can define a policy by setting the following header:
Content-Security-Policy: default-src https:; script-src 'nonce-{random}'; object-src 'none'
Real policies are typically more complicated. The above example policy requires all resources to load over HTTPS, allows only script
elements with the correct nonce
attribute, and prevents plugins from loading.
Errors caused by CSP
If you notice any of the following issues after installing Pendo, you might need to check your CSP.
- No analytics or guide events appearing for your application.
- Guides not loading at all in your application.
- Visual Design Studio not launching.
- No replays appearing for your application.
- Error messages in your console that look like the following:

Find your current CSP
To find your current CSP:
-
Open the Network tab in your browser console.
- Open the request of the main page.
-
Find the CSP listed under
Content-Security-Policy
in the Headers tab.

- If there’s no CSP response header, inspect the HTML of the page and look for a Content-Security-Policy
<meta>
tag in the <head>
of the document.

Standard required directives
Required directives are different depending on your agent delivery settings. To know which directives are required for Pendo to work fully in your application, you must first take note of your guide delivery settings. To find these:
-
Navigate to Settings > Subscription Settings.
-
Open the Applications tab.
-
Find and open the relevant app from your Applications list.
-
Open the Agent Settings tab.
-
Select Manage Production Settings.
-
Note which option is selected: Standards, XHR, or JSONP.
The following directive changes are required for Pendo to have full functionality with a strict CSP. These are organized by the following content types:
- JavaScript (directive:
script-src
)
- CSS (directive:
style-src
)
- Images (directive:
img-src
)
- Data (directive:
connect-src
)
- Frames (directives:
frame-src
and frame-ancestors
)
- Workers (directive:
worker-src
)
Replace SUB_ID
with your Subscription ID. Your Subscription ID is displayed in the page URL when you're logged into Pendo. It uses the following formathttps://app.pendo.io/s/[SUB_ID]/
. The subscription ID immediately follows /s/
. Don't accidentally grab the unique ID for a guide or report that populates at the end of the URL path when navigating Pendo.
You may include https://
before any hostnames if desired.
JavaScript directive changes
Directive: script-src
Images directive changes
Directive: img-src
The following sources allow images hosted by Pendo to be displayed on your site.
Source |
Description |
cdn.pendo.io |
Only needed for badges in classic guides.
|
data.pendo.io |
Events are sent using the image src to this url. Needed to send events to Pendo.
|
pendo-static-{{ SUB_ID }}.storage.googleapis.com |
Guide images are downloaded from this url. Needed to download any uploaded guide images.
|
app.pendo.io |
Only required to use the designer.
|
data: |
Default badge images. If using custom images for badges, then this isn't needed.
|
Data directive changes
Directive: connect-src
Source |
Description |
data.pendo.io |
Required for event communication and Session Replay. |
pendo-static-{{ SUB_ID }}.storage.googleapis.com |
Load the guide structure files here. Needed to load guide content.
|
app.pendo.io |
Only required to use the Visual Design Studio.
|
Frame directive changes
Directive: frame-src
The following source allows Pendo to load the Visual Design Studio within a <frame>
over your site.
Source |
Description |
app.pendo.io |
The Visual Design Studio is loaded from this URL. Only required to design guides with the Visual Design Studio.
|
Directive: frame-ancestors
The following source allows Pendo to load your site pages within a <frame>
, which is only needed if you're using the Classic Designer.
Source |
Description |
app.pendo.io |
The Pendo host from where the Classic Designer loads your application. Only required to design guides with the Classic Designer.
|
Workers directive changes
Directive: worker-src
The following source allows the Pendo agent to start a worker thread to minimize performance impact on your application.
Source |
Description |
blob: |
The Pendo agent starts a web worker to compress and send session-capturing data for Session Replay. Offloading work to a worker allows for improved performance of session capturing.
|
Location-based changes
This section lists location-based changes to the source for EU, US1, and Japan customers.
EU
Original
|
EU |
app.pendo.io |
app.eu.pendo.io |
data.pendo.io |
data.eu.pendo.io
|
cdn.pendo.io |
cdn.eu.pendo.io
|
pendo-io-static.storage.googleapis.com |
pendo-eu-static.storage.googleapis.com
|
pendo-static-{{ SUB_ID }}.storage.googleapis.com |
pendo-eu-static-{{ SUB_ID }}.storage.googleapis.com
|
Original
|
US1 |
app.pendo.io |
app.us1.pendo.io |
data.pendo.io |
data.us1.pendo.io
|
cdn.pendo.io |
cdn.us1.pendo.io
|
pendo-io-static.storage.googleapis.com |
pendo-us1-static.storage.googleapis.com
|
pendo-static-{{ SUB_ID }}.storage.googleapis.com |
pendo-us1-static-{{ SUB_ID }}.storage.googleapis.com
|
Japan
Original
|
Japan |
app.pendo.io |
app.jp.pendo.io |
data.pendo.io |
data.jp.pendo.io
|
cdn.pendo.io |
cdn.jp.pendo.io
|
pendo-io-static.storage.googleapis.com |
pendo-jp-static.storage.googleapis.com
|
pendo-static-{{ SUB_ID }}.storage.googleapis.com |
pendo-jp-static-{{ SUB_ID }}.storage.googleapis.com
|
Required directives for custom CNAME
If you're using CSP with CNAME, add the sources below to the existing Pendo standard required directives while setting up CNAME with Pendo's Support team. After CNAME configuration is complete, directives can be trimmed down.
JavaScript directive changes
Directive: script-src
Images directive changes
Directive: img-src
The following sources allow images hosted by Pendo to be displayed on your site.
Source |
Description |
content.pendo.example.com |
Guide images are downloaded from this URL.
|
data.pendo.example.com |
Events are sent using the image src to this url. Needed to send events to Pendo.
|
app.pendo.io |
Only required to use the designer.
|
data: |
Default badge images. If using custom images for badges, then this isn't needed.
|
Data directive changes
Directive: connect-src
The following sources allow scripts on your pages to communicate with Pendo.
Compatible guide content
While Pendo is compatible with strict CSP directives, it is the user’s responsibility to ensure the guide content is compatible with your CSP restrictions.
If unsafe-inline
is not present within the style-src
and script-src
directives, inline CSS and JavaScript within the HTML tab of the guide will not function correctly. To prevent an unexpected guide experience, all inline styles and scripts should be moved to the CSS and JS tabs of the guide code block or template.
With properly set minimal CSP directives (no inline directives), you should be able to fully use the Pendo Designer to show and tag your features. The X-Frame-Options plugin should enable you to use the Designer in guide editing mode with strict CSP. It is important to test guide content outside of the designer and with the X-Frame-Options plugin turned off.
Example of strict CSP compatible content
The basic concept is to remove all "unsafe-inline" styling and JavaScript.
For example, all of the inline styling and JavaScript within this HTML button:
<button class="_pendo-guide-next_" style="color:blue;" onclick="pendo.onGuideAdvanced()">Next</button>
HTML
<button class="_pendo-guide-next_ blue-button">Next</button>
CSS
.bluebutton { color: blue; }
JavaScript
(function wireGuideAdvanceButton (step) { step && step.attachEvent(step.guideElement[0], 'click', function (e) { var advanceButton = pendo.dom(e.target || e.srcElement).closest('._pendo-guide-next_'); if (advanceButton.length) { pendo.onGuideAdvanced(); } }); })(step,guide);
Trusted types are an experimental technology currently only supported by Chromium-based browsers. If your application requires the extra XSS protection provided by trusted types, add the following directive to your CSP header: trusted-types pendo;
. Trusted types support requires agent version 2.184.0 or higher.