Pendo’s product analytic capabilities can be particularly helpful with single-page application frameworks. Traditional Web analytic tools struggle in these environments because they're tailored around page views. Within a single-page framework, many different user interactions can happen within a single page view.
Development teams can work around these issues, but it adds additional workload to ensure that the analytic solutions are tracking properly. Pendo gets around these challenges by capturing all user interactions on the page and attributing them to specific users. To do this, Pendo requires the insertion of a small JavaScript snippet in your application. This snippet securely and asynchronously loads a Javascript file from our CDN.
Your install script ("snippet")
Your Pendo installation snippet can be found on the Install Settings page (only accessible by admins) and can be inserted into your common HTML template as-is for most apps. It can take up to two hours for data to feed into Pendo. You receive an e-mail once we begin receiving data.
Installation process
The installation approach is similar to a multi-page installation where the same install script (commonly referred to as "the snippet") is used. However, it's deployed slightly differently. With a single-page framework, the first part of the Pendo install script, function(p,e,n,d,o){}
is added to the application library, and then the second half, pendo.initialize({})
, is loaded with the page once the application has user-identifying information to share with Pendo.
Our Agent 2.0 FAQ includes more information on the install script and how the Pendo Agent is updated.
Warning: All snippets shown here are samples to illustrate how you need to adjust your provided JavaScript Snippet. To ensure you're copying and modifying your snippet with your unique API key, don't copy directly from this article.
Here is a sample snippet to show you how to break up the snippet for installation:
<script>
(function(apiKey){
(function(p,e,n,d,o){var v,w,x,y,z;o=p[d]=p[d]||{};o._q=o._q||[];
v=['initialize','identify','updateOptions','pageLoad','track'];for(w=0,x=v.length;w<x;++w)(function(m){
o[m]=o[m]||function(){o._q[m===v[0]?'unshift':'push']([m].concat([].slice.call(arguments,0)));};})(v[w]);
y=e.createElement(n);y.async=!0;y.src='https://cdn.pendo.io/agent/static/'+apiKey+'/pendo.js';
z=e.getElementsByTagName(n)[0];z.parentNode.insertBefore(y,z);})(window,document,'script','pendo');
// This function creates anonymous visitor IDs in Pendo unless you change the visitor id field to use your app's values
// This function uses the placeholder 'ACCOUNT-UNIQUE-ID' value for account ID unless you change the account id field to use your app's values
// Call this function after users are authenticated in your app and your visitor and account id values are available
// Please use Strings, Numbers, or Bools for value types.
pendo.initialize({
visitor: {
id: 'VISITOR-UNIQUE-ID' // Required if user is logged in, default creates anonymous ID
// email: // Recommended if using Pendo Feedback, or NPS Email
// full_name: // Recommended if using Pendo Feedback
// role: // Optional
// You can add any additional visitor level key-values here,
// as long as it's not one of the above reserved names.
},
account: {
id: 'ACCOUNT-UNIQUE-ID' // Required if using Pendo Feedback, default uses the value 'ACCOUNT-UNIQUE-ID'
// name: // Optional
// is_paying: // Recommended if using Pendo Feedback
// monthly_value:// Recommended if using Pendo Feedback
// planLevel: // Optional
// planPrice: // Optional
// creationDate: // Optional
// You can add any additional visitor level key-values here,
// as long as it's not one of the above reserved names.
}
});
})('ACTUAL_API_KEY_HERE');
</script>
Part 1 of install script
For example, you would add the following portion of the install script to your application library or index page:
<script>
(function(apiKey){
(function(p,e,n,d,o){var v,w,x,y,z;o=p[d]=p[d]||{};o._q=o._q||[];
v=['initialize','identify','updateOptions','pageLoad','track'];for(w=0,x=v.length;w<x;++w)(function(m){
o[m]=o[m]||function(){o._q[m===v[0]?'unshift':'push']([m].concat([].slice.call(arguments,0)));};})(v[w]);
y=e.createElement(n);y.async=!0;y.src='https://cdn.pendo.io/agent/static/'+apiKey+'/pendo.js';
z=e.getElementsByTagName(n)[0];z.parentNode.insertBefore(y,z);})(window,document,'script','pendo');
})('ACTUAL_API_KEY_HERE');
</script>
Part 2 of install script
Once you have the user context within the application, you use the second half of the install script to pass the user, account, and any additional demographic information to Pendo:
// This function creates anonymous visitor IDs in Pendo unless you change the visitor id field to use your app's values
// This function uses the placeholder 'ACCOUNT-UNIQUE-ID' value for account ID unless you change the account id field to use your app's values
// Call this function after users are authenticated in your app and your visitor and account id values are available
// Please use Strings, Numbers, or Bools for value types.
pendo.initialize({
visitor: {
id: 'VISITOR-UNIQUE-ID' // Required if user is logged in, default creates anonymous ID
// email: // Recommended if using Pendo Feedback, or NPS Email
// full_name: // Recommended if using Pendo Feedback
// role: // Optional
// You can add any additional visitor level key-values here,
// as long as it's not one of the above reserved names.
},
account: {
id: 'ACCOUNT-UNIQUE-ID' // Required if using Pendo Feedback, default uses the value 'ACCOUNT-UNIQUE-ID'
// name: // Optional
// is_paying: // Recommended if using Pendo Feedback
// monthly_value:// Recommended if using Pendo Feedback
// planLevel: // Optional
// planPrice: // Optional
// creationDate: // Optional
// You can add any additional visitor level key-values here,
// as long as it's not one of the above reserved names.
}
});
If your application uses TypeScript, you must use window.pendo.initialize()
or (window as any).pendo.initialize()
instead of calling Pendo directly.
Frequently asked questions
Where do I install the install script? Everywhere!
The install script (snippet) must be installed on every page. If your site uses iframes, you must ensure that Pendo is installed in each of these frames.
Why do universally Unique IDs matter?
Unique Visitor and Account IDs identify your end-users and customers, respectively. If any of these are duplicated, multiple users’ data could be aggregated under a single ID. For more information, see Planning your Pendo installation.
Why does metadata matter?
You will be able to segment visitors based on any metadata you pass to Pendo. For example, you might want to pass us the role of each user so that you can eventually target guides or filter data toward specific roles. For more information, see Planning your Pendo installation.
Who are unknown/anonymous users?
Unknown or anonymous users are visitors who don’t sign in to your app. If you would like to see the data of anonymous visitors or would like your anonymous visitors to see your guides, you can enable analytics on your unknown users. For more information, see Anonymous Visitors.
How do I hide data that I don’t want to see?
Between testing and staging environments, and internal users versus visitors, data can get messy. If you have data you don't want to be included, you can exclude it. Pendo can hide data based on Server/Host Domain, IP Address, Visitor ID, or Account ID.
What about URLs?
Pendo relies on the URL to distinguish between different pages of the application. If the URL doesn't change as the user navigates through the application, we recommend implementing the Location API.
What if visitor or account data changes without a window reload?
We have some functions that can either modify optional fields or reinitialize a session with a new Visitor or Account ID.
If you're modifying additional metadata associated with a visitor, call pendo.updateOptions()
.
If you need to change a Visitor or Account ID, call pendo.identify()
and pass in your vVsitor or Account IDs as you would in the initialization.
Learn more about our initialization and identification functions in the developer docs.
Validation and troubleshooting
How do I validate that my installation is correct?
To check the status of your install and if metadata is set for a particular user, you can do the following:
- After installing Pendo, open your application in a browser tab.
- Sign in as a user.
- Open the Browser Developer Console.
- Type
pendo.validateInstall()
into the console and press enter.
This returns information on the visitor’s identifiable metadata.
Why does my data not appear in Pendo?
Confirm that your API Key has been included in the install script. If you copy the code block from your Install Settings page, the API Key is already included. If you pull the code block from somewhere else, confirm that the API Key is present.
There are data syntax rules you must follow for Pendo to receive all of your data. Don't send null
values for any fields. If you don't have data for a field, don't send that field. Don't include a space in any custom fields added in the install script. This field must start with a letter or underscore and can follow with any combination of letters or numbers, as well as an underscore. For more information, see Visitor and Account Metadata.
Note: Data doesn't appear instantly. It's batch aggregated at the top of every hour and can take up to 15 minutes past the hour to fully appear in the Pendo UI.
pendo.js and pendo-staging.js
The Pendo install script first loads the pendo.js agent. The agent checks if the server hostname matches a staging server rule and, if so, loads the pendo object from pendo-staging.js instead of pendo.js.
No logged-in users
During setup, the message "No Logged In Users" informs that Pendo is receiving basic data from your application (specifically that Pages and Features are being used in your app), but there's no user-identifying information. While you can still use Pendo without this data, the functionality is greatly reduced.
In the install script, there are two blocks of interest for this issue: the Visitor block and the Account block. The data is either not being passed or it's structured incorrectly.
Here is the template for this code:
visitor: {
id: 'VISITOR-UNIQUE-ID' // Required if user is logged in
// email: // Recommended if using Pendo Feedback, or NPS Email
// full_name: // Recommended if using Pendo Feedback
// role: // Optional
// You can add any additional visitor level key-values here,
// as long as it's not one of the above reserved names.
},
account: {
// id: 'ACCOUNT-UNIQUE-ID' // Highly recommended
// name: // Optional
// is_paying: // Recommended if using Pendo Feedback
// monthly_value:// Recommended if using Pendo Feedback
// planLevel: // Optional
// planPrice: // Optional
// creationDate: // Optional
// You can add any additional account level key-values here,
// as long as it's not one of the above reserved names.
}
This is an example of what the data could look like in your code:
visitor: {
id: $user.ID,
email: '$user.email',
full_name: '$user.full_name',
role: '$user.accessLevel',
creationDate: $user.creationDate
},
account: {
id: '$account.ID',
name: '$account.name',
is_paying: $account.is_paying,
monthly_value:'$account.monthly_value',
planLevel: $account.subscriptionCost,
isFoo: $account.isFoo
}
This is an example of what the code would look like after it is processed and sent to Pendo.
visitor: {
id: 62343,
email: 'john@doe.com',
full_name: 'John Doe',
role: 'admin',
creationDate: 1404326949156
},
account: {
id: 17,
name: 'Acme, inc',
is_paying: true,
monthly_value:'99.99',
planLevel: 995,
isFoo: false
}
Pendo performance
Pendo’s Javascript files are hosted and served on Amazon’s Cloudfront CDN utilizing state-of-the-art edge caching. The javascript file is minified to only 54K bytes and loads asynchronously.
Data is securely transmitted through TLS from each user’s browser to our server every two minutes and when a page is ‘unloaded.’ Data is compressed before sending and each transmission is less than 2K bytes.
For more information, see the Security and Privacy article.
Optional flags
You can add optional flags to the JavaScript code block. For more information, see the Developer's guide to installing Pendo, which also includes additional FAQs.