tessl install tessl/npm-posthog-js@1.335.0PostHog Browser JS Library is a comprehensive browser analytics and feature management SDK that enables developers to capture user events, track product analytics, manage feature flags, record session replays, and implement feedback mechanisms like surveys and conversations in web applications.
Practical examples and patterns for common use cases.
import posthog from 'posthog-js';
// Initialize with e-commerce optimizations
posthog.init('your-api-key', {
api_host: 'https://us.i.posthog.com',
autocapture: true,
capture_pageview: 'history_change',
session_recording: {
enabled: true,
maskAllInputs: true,
blockSelector: '.payment-info, .credit-card'
}
});
// Track product views
function trackProductView(product: Product) {
posthog.capture('product_viewed', {
product_id: product.id,
product_name: product.name,
product_price: product.price,
product_category: product.category
});
}
// Track add to cart
function trackAddToCart(product: Product, quantity: number) {
posthog.capture('product_added_to_cart', {
product_id: product.id,
quantity: quantity,
price: product.price,
cart_total: getCartTotal()
});
}
// Track purchase
function trackPurchase(order: Order) {
posthog.capture('purchase_completed', {
order_id: order.id,
total: order.total,
currency: order.currency,
items: order.items.map(item => ({
product_id: item.productId,
quantity: item.quantity,
price: item.price
})),
payment_method: order.paymentMethod
}, {
send_instantly: true // Critical event
});
}// Track onboarding steps
class OnboardingTracker {
trackStep(stepName: string, stepNumber: number, totalSteps: number) {
posthog.capture('onboarding_step_completed', {
step_name: stepName,
step_number: stepNumber,
total_steps: totalSteps,
completion_percentage: (stepNumber / totalSteps) * 100
});
}
trackCompletion(timeSpent: number) {
posthog.capture('onboarding_completed', {
time_spent_seconds: timeSpent,
completion_date: new Date().toISOString()
});
// Set user property
posthog.setPersonProperties({
onboarding_completed: true,
onboarding_completed_at: new Date().toISOString()
});
}
}
// Usage
const tracker = new OnboardingTracker();
function completeStep(step: number) {
tracker.trackStep(`step_${step}`, step, 5);
if (step === 5) {
tracker.trackCompletion(calculateTimeSpent());
}
}// Track feature usage
function trackFeatureUsage(featureName: string, action: string) {
posthog.capture('feature_used', {
feature_name: featureName,
action: action,
user_plan: posthog.get_property('plan'),
days_since_signup: calculateDaysSinceSignup()
});
// Update feature usage count
posthog.setPersonProperties({
[`${featureName}_usage_count`]: 1 // Increments
});
}
// Track feature discovery
function trackFeatureDiscovery(featureName: string, discoveryMethod: string) {
posthog.capture('feature_discovered', {
feature_name: featureName,
discovery_method: discoveryMethod, // 'tooltip', 'menu', 'search', etc.
time_to_discovery: calculateTimeToDiscovery()
});
}// Track organization-level analytics
function setupOrganizationTracking(user: User, org: Organization) {
// Identify user
posthog.identify(user.id, {
email: user.email,
name: user.name,
role: user.role
});
// Associate with organization
posthog.group('organization', org.id, {
name: org.name,
plan: org.plan,
created_at: org.createdAt,
user_count: org.userCount,
mrr: org.mrr
});
// Reload flags for org-specific features
posthog.reloadFeatureFlags();
}
// Track organization events
function trackOrgEvent(event: string, properties: Properties = {}) {
const groups = posthog.getGroups();
posthog.capture(event, {
...properties,
organization_id: groups.organization
});
}// Track reading behavior
class ArticleTracker {
private startTime: number = Date.now();
private maxScroll: number = 0;
trackArticleView(article: Article) {
posthog.capture('article_viewed', {
article_id: article.id,
article_title: article.title,
article_category: article.category,
article_author: article.author,
word_count: article.wordCount
});
this.setupScrollTracking();
this.setupTimeTracking();
}
setupScrollTracking() {
window.addEventListener('scroll', () => {
const scrollPercent = (window.scrollY /
(document.body.scrollHeight - window.innerHeight)) * 100;
if (scrollPercent > this.maxScroll) {
this.maxScroll = scrollPercent;
}
});
}
setupTimeTracking() {
window.addEventListener('beforeunload', () => {
const timeSpent = Date.now() - this.startTime;
posthog.capture('article_engagement', {
time_spent_seconds: Math.floor(timeSpent / 1000),
scroll_depth_percent: Math.floor(this.maxScroll),
completed: this.maxScroll > 90
});
});
}
}// Track device capabilities and usage
function setupDeviceTracking() {
const deviceInfo = {
device_type: getDeviceType(),
screen_size: `${window.screen.width}x${window.screen.height}`,
viewport_size: `${window.innerWidth}x${window.innerHeight}`,
pixel_ratio: window.devicePixelRatio,
touch_support: 'ontouchstart' in window,
orientation: window.screen.orientation?.type
};
posthog.register(deviceInfo);
// Track orientation changes
window.addEventListener('orientationchange', () => {
posthog.capture('orientation_changed', {
new_orientation: window.screen.orientation?.type
});
});
}
function getDeviceType(): string {
const width = window.innerWidth;
if (width < 768) return 'mobile';
if (width < 1024) return 'tablet';
return 'desktop';
}// Track PWA installation
window.addEventListener('beforeinstallprompt', (e) => {
posthog.capture('pwa_install_prompt_shown');
e.preventDefault();
// Show custom install button
showInstallButton(() => {
e.prompt();
e.userChoice.then((choice) => {
posthog.capture('pwa_install_prompt_result', {
outcome: choice.outcome // 'accepted' or 'dismissed'
});
});
});
});
// Track successful installation
window.addEventListener('appinstalled', () => {
posthog.capture('pwa_installed', {
install_date: new Date().toISOString()
});
posthog.setPersonProperties({
pwa_installed: true
});
});
// Track standalone mode usage
if (window.matchMedia('(display-mode: standalone)').matches) {
posthog.register({
app_mode: 'standalone'
});
}// Track AI interactions
class AIInteractionTracker {
async trackGeneration(prompt: string, model: string) {
const traceId = `trace_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
const startTime = Date.now();
// Track start
posthog.capture('ai_generation_started', {
trace_id: traceId,
model: model,
prompt_length: prompt.length
});
try {
// Generate response
const response = await generateAIResponse(prompt, model);
const duration = Date.now() - startTime;
// Track metrics
posthog.captureTraceMetric(traceId, 'duration_ms', duration);
posthog.captureTraceMetric(traceId, 'prompt_tokens', response.usage.promptTokens);
posthog.captureTraceMetric(traceId, 'completion_tokens', response.usage.completionTokens);
posthog.captureTraceMetric(traceId, 'total_cost_usd', response.cost);
// Track completion
posthog.capture('ai_generation_completed', {
trace_id: traceId,
success: true
});
return { traceId, response };
} catch (error) {
posthog.captureException(error, {
trace_id: traceId,
model: model
});
throw error;
}
}
trackFeedback(traceId: string, helpful: boolean, comment?: string) {
const feedback = JSON.stringify({
helpful: helpful,
comment: comment,
timestamp: new Date().toISOString()
});
posthog.captureTraceFeedback(traceId, feedback);
}
}// Run A/B test with tracking
function setupExperiment(experimentKey: string) {
posthog.onFeatureFlags((flags) => {
const variant = flags[experimentKey];
if (variant) {
// Track exposure
posthog.capture('experiment_viewed', {
experiment: experimentKey,
variant: variant,
session_id: posthog.get_session_id()
});
// Apply variant
applyVariant(variant);
// Track interactions
trackVariantInteractions(experimentKey, variant);
}
});
}
function trackVariantInteractions(experiment: string, variant: string) {
// Track conversions
document.querySelectorAll('.conversion-button').forEach(button => {
button.addEventListener('click', () => {
posthog.capture('experiment_conversion', {
experiment: experiment,
variant: variant,
conversion_type: 'button_click'
});
});
});
}// Initialize with GDPR compliance
posthog.init('your-api-key', {
opt_out_capturing_by_default: true,
opt_out_persistence_by_default: true,
respect_dnt: true,
session_recording: {
maskAllInputs: true,
blockSelector: '.sensitive-data'
}
});
// Show consent banner
function showConsentBanner() {
const banner = createBanner({
onAccept: () => {
posthog.opt_in_capturing({
captureEventName: 'gdpr_consent_granted'
});
posthog.startSessionRecording();
},
onReject: () => {
posthog.opt_out_capturing();
}
});
}
// Check consent on load
if (posthog.get_explicit_consent_status() === 'pending') {
showConsentBanner();
}// Set up global error tracking
function setupErrorTracking() {
// Enable autocapture
posthog.startExceptionAutocapture({
capture_unhandled_errors: true,
capture_unhandled_rejections: true
});
// Link errors to session replays
window.addEventListener('error', (event) => {
posthog.captureException(event.error, {
session_replay_url: posthog.get_session_replay_url({
withTimestamp: true,
timestampLookBack: 30
}),
page_url: window.location.href
});
});
}For more detailed implementations, see: