Install Pendo | OpsBlu Docs

Install Pendo

Install the Pendo tracking tag or SDK — step-by-step embed instructions, verification, and troubleshooting.

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:

  1. Log into your Pendo account
  2. Navigate to Settings > Subscription Settings
  3. Click on "Install Settings"
  4. 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

  1. In GTM, create a new Tag
  2. Choose "Custom HTML" as tag type
  3. 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>
  1. Set trigger to "All Pages" or specific page views
  2. Publish the container

WordPress Integration

  1. Install "Insert Headers and Footers" plugin
  2. Go to Settings > Insert Headers and Footers
  3. Paste the Pendo snippet in the header section
  4. 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

  1. Open browser DevTools
  2. Go to Network tab
  3. Filter for "pendo"
  4. Look for requests to cdn.pendo.io and app.pendo.io

Pendo Dashboard

  1. Log into Pendo
  2. Go to Visitors > Visitor Details
  3. Search for your visitor ID
  4. 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;
}

Additional Resources