Event Tracking
Pendo provides multiple methods for tracking user interactions and events in your application. From code-based track events to visual tagging without code, Pendo offers flexible solutions for capturing user behavior.
Track Events API
The pendo.track() method allows you to programmatically send custom events to Pendo with associated metadata.
Basic Event Tracking
// Simple event without metadata
pendo.track('Button Clicked');
// Event with metadata
pendo.track('Purchase Completed', {
product_id: '12345',
product_name: 'Premium Plan',
price: 99.99,
currency: 'USD'
});
Common Event Patterns
User Actions
// Button clicks
document.querySelector('#checkout-btn').addEventListener('click', () => {
pendo.track('Checkout Button Clicked', {
page: 'cart',
items_count: cart.items.length,
total_value: cart.total
});
});
// Form submissions
form.addEventListener('submit', (e) => {
pendo.track('Contact Form Submitted', {
form_name: 'contact',
source_page: window.location.pathname
});
});
Business Events
// Successful purchase
function onPurchaseSuccess(order) {
pendo.track('Order Placed', {
order_id: order.id,
revenue: order.total,
items: order.items.length,
payment_method: order.paymentMethod,
shipping_method: order.shippingMethod
});
}
// Subscription changes
function onSubscriptionUpgrade(subscription) {
pendo.track('Subscription Upgraded', {
from_plan: subscription.oldPlan,
to_plan: subscription.newPlan,
mrr_change: subscription.mrrDelta,
effective_date: subscription.effectiveDate
});
}
Feature Usage
// Feature activation
pendo.track('Feature Enabled', {
feature_name: 'Advanced Analytics',
feature_tier: 'enterprise',
user_role: currentUser.role
});
// Export actions
pendo.track('Report Exported', {
report_type: 'monthly_summary',
format: 'pdf',
date_range: '2024-01-01_to_2024-01-31'
});
Visual Tagging with Pendo Designer
Pendo's Visual Designer allows you to tag page views and features without writing code. This is ideal for:
- Non-technical team members
- Rapid iteration and testing
- Tagging UI elements that don't have click handlers
How to Use Visual Designer
Access Designer
- Log into Pendo
- Navigate to Settings > Install Settings
- Click "Launch Designer"
Tag Features
- Navigate to the page in your application
- Click on elements to select them
- Name the feature and save
Configure Rules
- Set visibility rules
- Define page matching rules
- Add custom CSS selectors if needed
Visual Designer Best Practices
// Make tagging easier by adding data attributes
<button
class="btn btn-primary"
data-pendo="checkout-button"
data-pendo-action="initiate-checkout">
Checkout
</button>
This makes elements easier to identify in the Visual Designer and creates more stable selectors.
Auto-Captured Events
Pendo automatically captures certain events without additional configuration:
Page Views
Pendo automatically tracks page views in single-page applications and traditional websites:
// Automatically tracked on route change
// No additional code needed
// Optionally trigger manually for custom routing
pendo.pageLoad();
Feature Clicks
Once tagged in Visual Designer, feature clicks are automatically tracked:
// Tagged features automatically send events
// View in Pendo: Behavior > Features > [Feature Name]
Track Events in Different Frameworks
React
import { useEffect } from 'react';
function CheckoutButton() {
const handleCheckout = () => {
pendo.track('Checkout Initiated', {
component: 'CheckoutButton',
cart_value: cart.total
});
// Your checkout logic
};
return (
<button
Checkout
</button>
);
}
Angular
import { Component } from '@angular/core';
@Component({
selector: 'app-purchase',
templateUrl: './purchase.component.html'
})
export class PurchaseComponent {
completePurchase() {
(window as any).pendo.track('Purchase Completed', {
product: this.selectedProduct.name,
price: this.selectedProduct.price
});
// Purchase logic
}
}
Vue
<template>
<button @click="handleClick">Subscribe</button>
</template>
<script>
export default {
methods: {
handleClick() {
window.pendo.track('Subscribe Button Clicked', {
plan: this.selectedPlan,
monthly_price: this.planPrice
});
// Subscription logic
}
}
}
</script>
Event Metadata Best Practices
Data Types
pendo.track('Event Name', {
// Strings
user_role: 'admin',
// Numbers
quantity: 5,
price: 99.99,
// Booleans
is_trial: true,
has_discount: false,
// Dates (as ISO strings)
event_date: new Date().toISOString(),
// Arrays (as JSON strings)
selected_features: JSON.stringify(['analytics', 'reporting']),
// Objects (as JSON strings)
metadata: JSON.stringify({
source: 'mobile_app',
version: '2.1.0'
})
});
Naming Conventions
Use consistent, descriptive names:
// Good: Clear, descriptive, consistent
pendo.track('Shopping Cart Abandoned', {
cart_value: 150.00,
items_count: 3,
abandonment_stage: 'checkout'
});
// Avoid: Vague, inconsistent
pendo.track('cart_event', {
val: 150.00,
num: 3,
stage: 'checkout'
});
Tracking User Lifecycle Events
Onboarding
// Welcome flow start
pendo.track('Onboarding Started', {
user_type: 'new',
source: 'email_invite'
});
// Onboarding step completion
pendo.track('Onboarding Step Completed', {
step_number: 3,
step_name: 'Profile Setup',
time_spent_seconds: 45
});
// Onboarding completion
pendo.track('Onboarding Completed', {
total_steps: 5,
total_time_seconds: 300,
completion_rate: 100
});
Engagement Milestones
// First action
pendo.track('First Report Created', {
days_since_signup: 2,
report_type: 'sales_dashboard'
});
// Achievement unlocked
pendo.track('Milestone Reached', {
milestone: '100_reports_created',
user_tenure_days: 90
});
Debugging Track Events
Enable Debugging
// In browser console
pendo.setDebugMode(true);
// Track an event and see console output
pendo.track('Test Event', { test: true });
Verify Events
// Check if event was sent
pendo.track('Button Clicked', { button_id: 'submit' });
// Events appear in:
// 1. Browser Network tab (look for pendo API calls)
// 2. Pendo dashboard: Data Mappings > Track Events
// 3. Browser console (when debug mode enabled)
Track Events Data Governance
Event Schema Documentation
Maintain a centralized list of all tracked events:
// events.js - Event catalog
export const EVENTS = {
PURCHASE_COMPLETED: 'Purchase Completed',
SUBSCRIPTION_UPGRADED: 'Subscription Upgraded',
FEATURE_ENABLED: 'Feature Enabled'
};
export const EVENT_PROPERTIES = {
[EVENTS.PURCHASE_COMPLETED]: {
order_id: 'string',
revenue: 'number',
items: 'number'
}
};
// Usage
import { EVENTS } from './events';
pendo.track(EVENTS.PURCHASE_COMPLETED, {
order_id: order.id,
revenue: order.total,
items: order.items.length
});
Data Quality Checks
// Validation wrapper
function trackValidatedEvent(eventName, properties) {
// Validate required properties
const schema = EVENT_PROPERTIES[eventName];
const errors = [];
for (const [key, type] of Object.entries(schema)) {
if (!(key in properties)) {
errors.push(`Missing required property: ${key}`);
} else if (typeof properties[key] !== type) {
errors.push(`Invalid type for ${key}: expected ${type}`);
}
}
if (errors.length > 0) {
console.error('Track event validation failed:', errors);
return;
}
pendo.track(eventName, properties);
}
Performance Considerations
Batch Events
For high-frequency events, consider batching:
let eventQueue = [];
let batchTimer = null;
function queueEvent(eventName, properties) {
eventQueue.push({ eventName, properties });
if (!batchTimer) {
batchTimer = setTimeout(() => {
eventQueue.forEach(({ eventName, properties }) => {
pendo.track(eventName, properties);
});
eventQueue = [];
batchTimer = null;
}, 1000); // Batch every second
}
}
Conditional Tracking
Only track events when necessary:
// Track only significant value changes
let lastReportedValue = 0;
function trackValueChange(newValue) {
const percentChange = Math.abs((newValue - lastReportedValue) / lastReportedValue);
// Only track if change is > 10%
if (percentChange > 0.1) {
pendo.track('Significant Value Change', {
old_value: lastReportedValue,
new_value: newValue,
percent_change: percentChange
});
lastReportedValue = newValue;
}
}