Installation
Pendo offers multiple installation methods to accommodate different application architectures and frameworks. Choose the method that best fits your technology stack and deployment requirements.
Getting Your API Key
Before installation, you'll need your Pendo API key:
- Log into your Pendo account
- Navigate to Settings > Subscription Settings
- Click on "Install Settings"
- Copy your API key (also called Install Snippet Key)
JavaScript Snippet Installation
The standard JavaScript snippet is the most common installation method, working with traditional websites and single-page applications.
Basic Snippet
Add this code to your HTML <head> tag, ideally as early as possible:
<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');
})('YOUR-API-KEY-HERE');
// Initialize Pendo
pendo.initialize({
visitor: {
id: 'VISITOR_ID' // Required: Unique identifier for the user
},
account: {
id: 'ACCOUNT_ID' // Recommended: Unique identifier for the account/tenant
}
});
</script>
Dynamic User Data
For authenticated applications, initialize Pendo after user data is available:
<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');
})('YOUR-API-KEY-HERE');
// Wait for user authentication
window.addEventListener('userAuthenticated', function(event) {
pendo.initialize({
visitor: {
id: event.detail.userId,
email: event.detail.email,
full_name: event.detail.fullName,
role: event.detail.role
},
account: {
id: event.detail.accountId,
name: event.detail.accountName,
plan: event.detail.plan
}
});
});
</script>
Conditional Loading
Load Pendo only for logged-in users or specific environments:
<script>
(function(apiKey){
// Only load Pendo in production for authenticated users
if (window.location.hostname === 'app.example.com' && window.currentUser) {
(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');
pendo.initialize({
visitor: {
id: window.currentUser.id,
email: window.currentUser.email
},
account: {
id: window.currentUser.accountId
}
});
}
})('YOUR-API-KEY-HERE');
</script>
NPM Package Installation
For modern JavaScript applications using build tools and package managers.
Installation
npm install @pendo/agent
Or with Yarn:
yarn add @pendo/agent
Basic Usage
import pendo from '@pendo/agent';
// Initialize Pendo
pendo.initialize({
apiKey: 'YOUR-API-KEY',
visitor: {
id: user.id,
email: user.email,
full_name: user.fullName
},
account: {
id: user.accountId,
name: user.accountName
}
});
With Environment Variables
import pendo from '@pendo/agent';
// Use environment variables for API key
if (process.env.REACT_APP_PENDO_API_KEY) {
pendo.initialize({
apiKey: process.env.REACT_APP_PENDO_API_KEY,
visitor: {
id: user.id
}
});
}
React Integration
Using React Hooks
import { useEffect } from 'react';
import { useAuth } from './hooks/useAuth';
function App() {
const { user, account } = useAuth();
useEffect(() => {
if (user && window.pendo) {
window.pendo.initialize({
visitor: {
id: user.id,
email: user.email,
full_name: user.fullName,
role: user.role
},
account: {
id: account.id,
name: account.name,
plan: account.plan
}
});
}
}, [user, account]);
return <div>Your App</div>;
}
React Context Provider
// PendoProvider.js
import React, { createContext, useEffect, useContext } from 'react';
import pendo from '@pendo/agent';
const PendoContext = createContext();
export function PendoProvider({ children, user, account }) {
useEffect(() => {
if (user && account) {
pendo.initialize({
apiKey: process.env.REACT_APP_PENDO_API_KEY,
visitor: {
id: user.id,
email: user.email,
full_name: user.fullName
},
account: {
id: account.id,
name: account.name
}
});
}
}, [user, account]);
return (
<PendoContext.Provider value={{ pendo }}>
{children}
</PendoContext.Provider>
);
}
export const usePendo = () => useContext(PendoContext);
// App.js
import { PendoProvider } from './PendoProvider';
import { useAuth } from './hooks/useAuth';
function App() {
const { user, account } = useAuth();
return (
<PendoProvider user={user} account={account}>
<YourAppComponents />
</PendoProvider>
);
}
Angular Integration
App Component
// app.component.ts
import { Component, OnInit } from '@angular/core';
import { AuthService } from './services/auth.service';
declare global {
interface Window {
pendo: any;
}
}
@Component({
selector: 'app-root',
templateUrl: './app.component.html'
})
export class AppComponent implements OnInit {
constructor(private authService: AuthService) {}
ngOnInit() {
this.authService.user$.subscribe(user => {
if (user && window.pendo) {
window.pendo.initialize({
visitor: {
id: user.id,
email: user.email,
full_name: user.fullName
},
account: {
id: user.accountId,
name: user.accountName
}
});
}
});
}
}
Angular Service
// pendo.service.ts
import { Injectable } from '@angular/core';
declare global {
interface Window {
pendo: any;
}
}
@Injectable({
providedIn: 'root'
})
export class PendoService {
initialize(visitor: any, account: any) {
if (window.pendo) {
window.pendo.initialize({
visitor,
account
});
}
}
track(eventName: string, properties?: any) {
if (window.pendo) {
window.pendo.track(eventName, properties);
}
}
updateOptions(options: any) {
if (window.pendo) {
window.pendo.updateOptions(options);
}
}
}
Vue Integration
Vue 3 Plugin
// plugins/pendo.js
export default {
install: (app, options) => {
const pendo = window.pendo;
app.config.globalProperties.$pendo = pendo;
app.provide('pendo', pendo);
// Initialize when user is available
if (options.user && options.account) {
pendo.initialize({
visitor: {
id: options.user.id,
email: options.user.email
},
account: {
id: options.account.id,
name: options.account.name
}
});
}
}
};
// main.js
import { createApp } from 'vue';
import App from './App.vue';
import PendoPlugin from './plugins/pendo';
const app = createApp(App);
// Add Pendo plugin
app.use(PendoPlugin, {
user: window.currentUser,
account: window.currentAccount
});
app.mount('#app');
Vue 3 Composable
// composables/usePendo.js
import { onMounted } from 'vue';
export function usePendo(user, account) {
onMounted(() => {
if (window.pendo && user.value && account.value) {
window.pendo.initialize({
visitor: {
id: user.value.id,
email: user.value.email
},
account: {
id: account.value.id,
name: account.value.name
}
});
}
});
const track = (eventName, properties) => {
if (window.pendo) {
window.pendo.track(eventName, properties);
}
};
return { track };
}
Next.js Integration
App Router (_app.js)
// pages/_app.js
import { useEffect } from 'react';
import { useRouter } from 'next/router';
function MyApp({ Component, pageProps }) {
const router = useRouter();
useEffect(() => {
// Initialize Pendo after authentication
if (pageProps.user && window.pendo) {
window.pendo.initialize({
visitor: {
id: pageProps.user.id,
email: pageProps.user.email
},
account: {
id: pageProps.user.accountId
}
});
}
}, [pageProps.user]);
// Track page changes
useEffect(() => {
const handleRouteChange = () => {
if (window.pendo) {
window.pendo.pageLoad();
}
};
router.events.on('routeChangeComplete', handleRouteChange);
return () => {
router.events.off('routeChangeComplete', handleRouteChange);
};
}, [router.events]);
return <Component {...pageProps} />;
}
export default MyApp;
Script Component
// pages/_document.js
import { Html, Head, Main, NextScript } from 'next/document';
import Script from 'next/script';
export default function Document() {
return (
<Html>
<Head>
<Script
id="pendo-snippet"
strategy="afterInteractive"
dangerouslySetInnerHTML={{
__html: `
(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');
})('${process.env.NEXT_PUBLIC_PENDO_API_KEY}');
`
}}
/>
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
Google Tag Manager Installation
Install Pendo via Google Tag Manager for easier management.
Create Custom HTML Tag
- In GTM, create a new Tag
- Choose "Custom HTML" as tag type
- Add the Pendo snippet:
<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');
})('YOUR-API-KEY');
// Initialize with dataLayer variables
pendo.initialize({
visitor: {
id: {{userId}},
email: {{userEmail}}
},
account: {
id: {{accountId}}
}
});
</script>
- Set trigger to "All Pages" or specific page views
- Publish the container
WordPress Integration
Using Plugin (Recommended)
- Install "Insert Headers and Footers" plugin
- Go to Settings > Insert Headers and Footers
- Paste the Pendo snippet in the header section
- Save changes
Manual Theme Integration
Edit your theme's header.php:
<!-- Add before closing </head> tag -->
<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');
})('YOUR-API-KEY');
<?php if (is_user_logged_in()): ?>
pendo.initialize({
visitor: {
id: '<?php echo get_current_user_id(); ?>',
email: '<?php echo wp_get_current_user()->user_email; ?>'
}
});
<?php endif; ?>
</script>
Verification
After installation, verify Pendo is working:
Browser Console Check
// Check if Pendo is loaded
console.log(window.pendo);
// Check visitor ID
console.log(pendo.getVisitorId());
// Check account ID
console.log(pendo.getAccountId());
// Enable debug mode
pendo.setDebugMode(true);
Network Tab
- Open browser DevTools
- Go to Network tab
- Filter for "pendo"
- Look for requests to
cdn.pendo.ioandapp.pendo.io
Pendo Dashboard
- Log into Pendo
- Go to Visitors > Visitor Details
- Search for your visitor ID
- Verify recent activity appears
Troubleshooting
Pendo Not Loading
// Check if script loaded
if (!window.pendo) {
console.error('Pendo failed to load');
}
// Check for Content Security Policy issues
// Add to CSP if needed:
// script-src https://cdn.pendo.io;
// connect-src https://app.pendo.io;
Initialization Errors
// Wrap in try-catch
try {
pendo.initialize({
visitor: { id: userId },
account: { id: accountId }
});
} catch (error) {
console.error('Pendo initialization error:', error);
}
Multiple Initializations
// Prevent multiple initializations
let pendoInitialized = false;
function initializePendo(visitor, account) {
if (pendoInitialized || !window.pendo) return;
pendo.initialize({ visitor, account });
pendoInitialized = true;
}