Developer

Analytics Integration Guide

This document describes the analytics integration architecture for the Agility CMS demo site, focusing on PostHog implementation with a platform-agnostic abstraction layer.

Overview

The analytics system provides:

  • Platform-agnostic tracking - Easy to swap PostHog for GA4, Amplitude, Mixpanel, etc.
  • User identification - Persistent user IDs with audience/region properties
  • Enhanced pageview tracking - Path, locale, UTM params, performance metrics
  • Engagement tracking - Scroll depth, time on page, outbound links
  • Personalization tracking - Audience/region-based content views
  • A/B test tracking - Experiment exposure and variant interactions
  • Conversion tracking - Goal completions and funnel analysis
  • Agility CMS context - Page IDs and component content IDs for CMS-level analytics

Architecture

Agility CMS Context

All analytics events automatically include Agility CMS identifiers, enabling queries like:

  • "Show engagement metrics grouped by pageID"
  • "Compare scroll depth across different contentID values"
  • "Which pages have the highest time-on-page?"

Tracked IDs

PropertySourceDescription
pageIDdata-agility-page attributeAgility CMS page ID
contentIDsdata-agility-dynamic-content + data-agility-component attributesArray of all content IDs on the page
contentIDNearest data-agility-componentSpecific component for interaction events
localeURL path (e.g., /en-us/...)Current language/locale

Example PostHog Queries

Engagement by Page ID:

Time on Page by Content:

Engagement by Locale:

Ensuring Components Have IDs

All Agility CMS components should include the data-agility-component attribute:

For client components, pass the contentID as a prop and use it on the wrapper element.

Quick Start

Basic Event Tracking

User Identification

Event Taxonomy

Core Events

EventPropertiesDescription
page_viewedpath, title, locale, audience, region, pageID, contentIDs, utmSource, etc.Page navigation
cta_clickedctaName, ctaUrl, ctaText, location, component, pageID, contentIDCTA interactions
scroll_milestonedepth (25/50/75/100), timeToReach, locale, pageID, contentIDsScroll engagement
time_milestoneseconds (30/60/120/300), isVisible, locale, pageID, contentIDsTime engagement
outbound_link_clickedurl, text, path, locale, pageID, contentIDExternal link clicks

Personalization Events

EventPropertiesDescription
personalization_appliedpersonalizationType, audience, regionContext detected
personalized_content_viewedcomponent, contentID, audience, regionPersonalized content shown
audience_changedaudience, previousAudience, pathUser changed audience
region_changedregion, previousRegion, pathUser changed region

Experiment Events

EventPropertiesDescription
experiment_exposureexperimentKey, variant, component, contentIDVariant shown
experiment_interactionexperimentKey, variant, action, componentUser interacted with variant

Conversion Events

EventPropertiesDescription
conversiongoalName, value, currency, metadataGoal completed
demo_requestedAll conversion propertiesDemo/contact form submitted
form_startedformName, stepForm interaction started
form_submittedformName, filledFieldsForm completed

User Properties

These properties are set on users for segmentation:

PropertyTypeDescription
audiencestringCurrent audience segment
regionstringCurrent region
localestringLanguage preference
first_seenISO dateFirst visit timestamp
session_countnumberTotal sessions

PostHog Dashboard Setup

See Also: Analytics Dashboard Reference for the pre-built demo dashboard with all insights configured.

Demo Dashboard

A pre-configured PostHog dashboard is available with 10 insights covering traffic, engagement, and personalization:

Dashboard URL: https://us.posthog.com/project/194639/dashboard/1135430

The dashboard includes:

  • Page Views Over Time
  • Top Pages by Traffic
  • Web Vitals Performance
  • Time on Page Milestones
  • Scroll Depth Distribution
  • Engagement Funnel
  • Personalization by Audience
  • Personalized Content Views by Component
  • Audience Segment Changes
  • Region Changes

Creating a Conversion Funnel

  1. Go to PostHog > Insights > New Insight > Funnel
  2. Add steps:
    • Step 1: page_viewed (entry)
    • Step 2: cta_clicked
    • Step 3: form_submitted
    • Step 4: conversion
  3. Break down by audience property to see conversion by segment

Creating an Audience Dashboard

  1. Traffic by Audience

    • Create a Trends insight
    • Event: page_viewed
    • Breakdown by: audience
    • Display: Bar chart
  2. Engagement by Audience

    • Create a Trends insight
    • Event: scroll_milestone where depth = 100
    • Breakdown by: audience
    • This shows which audiences read full pages
  3. Personalization Effectiveness

    • Create a Funnel insight
    • Step 1: personalized_content_viewed
    • Step 2: cta_clicked
    • Step 3: conversion
    • Breakdown by: audience
    • Compare personalized vs non-personalized conversion

A/B Test Analysis

See Also: A/B Testing Implementation Guide for complete implementation details, architecture decisions, and setup instructions.

A/B testing uses client-side feature flag evaluation with PostHog's useFeatureFlagVariantKey hook. This keeps routes static while PostHog handles experiment tracking automatically.

  1. Experiment Performance

    • Create a Funnel insight
    • Step 1: $feature_flag_called where $feature_flag = your-experiment
    • Step 2: cta_clicked or experiment_interaction
    • Step 3: conversion
    • Breakdown by: $feature_flag_response (variant)
  2. Using PostHog Experiments Dashboard

    • PostHog has built-in experiment analysis
    • Go to Experiments > Select your experiment
    • View statistical significance, conversion rates, and lift

Switching Analytics Providers

The analytics system is designed to be provider-agnostic. You can swap providers for both client-side and server-side tracking.

Graceful Degradation

If analytics credentials are not configured, the system gracefully degrades:

  • Client-side: PostHog won't initialize, tracking calls are silently skipped
  • Server-side: Feature flags return undefined (components use default variants), event tracking is skipped
  • No errors: The application works normally without analytics

Client-Side Provider Swap

To switch to a different client-side provider (e.g., Segment, Mixpanel):

  1. Create a new provider in src/lib/analytics/segment-provider.ts
  2. Implement the AnalyticsProvider interface
  3. Swap the provider in src/lib/analytics/index.ts
  1. Update src/instrumentation-client.ts to initialize your provider

Server-Side Provider Swap

Server-side analytics (for feature flags and server-side event tracking) is in src/lib/posthog/. Each file contains detailed comments showing alternative implementations:

FilePurposeAlternatives
get-client.tsAnalytics client initializationGA4 Measurement Protocol, Mixpanel, Amplitude, Segment
track-event.tsServer-side event trackingGA4, Mixpanel, Amplitude, Segment
get-feature-flag-variant.tsFeature flag evaluationLaunchDarkly, Split.io, Statsig, GrowthBook

Example environment variables for different providers:

Integrating with Other Tools

Heat Mapping (Hotjar, FullStory, etc.)

The analytics events can trigger heat mapping recordings:

Google Analytics 4

GA4 is supported in two ways:

  1. Client-side (recommended): Use @next/third-parties/google in layout.tsx:

  2. Server-side: Use the Measurement Protocol (see src/lib/posthog/track-event.ts for example)

The event taxonomy is already GA4-compatible.

Adding Tracking to Components

Server Components (RSC)

For server-rendered components, embed the PersonalizationTracker:

Client Components

Use the analytics API directly:

Forms

Track form interactions:

Testing Analytics

Development Mode

In development, all analytics calls are logged to the console:

PostHog Live Events

  1. Open PostHog dashboard
  2. Go to Events > Live Events
  3. Browse the site to see events in real-time

Browser DevTools

  1. Open Network tab
  2. Filter by "posthog"
  3. View event payloads being sent

Best Practices

  1. Use typed event helpers - trackCTAClick() instead of track('cta_clicked', ...)
  2. Include context - Always include path, audience, region when relevant
  3. Name events consistently - Use snake_case, be descriptive
  4. Track meaningful actions - Focus on user intent, not technical events
  5. Test before deploying - Verify events in PostHog Live Events
  6. Document custom events - Update this guide when adding new events

Troubleshooting

Analytics Not Configured (Expected Behavior)

If you haven't set up PostHog credentials, the system works normally:

  • No console errors about missing configuration
  • Feature flags return undefined, components use default variants
  • Event tracking calls are silently skipped
  • A/B tests show the control variant

This is intentional - analytics is optional.

Events Not Appearing

  1. Check PostHog is initialized (console log: "Initializing PostHog")
  2. Verify NEXT_PUBLIC_POSTHOG_KEY and NEXT_PUBLIC_POSTHOG_HOST are set
  3. Check Network tab for failed requests to PostHog

User Properties Not Set

  1. Ensure identify() is called before track()
  2. Check that user ID is being generated/retrieved
  3. Verify properties in PostHog > Persons

Scroll/Time Tracking Not Working

  1. Check if page has scrollable content
  2. Verify EngagementTracker is mounted (check React DevTools)
  3. Ensure page visibility is working (check console logs)

Feature Flags Not Working

  1. Verify PostHog credentials are set
  2. Check the feature flag exists in PostHog dashboard
  3. Ensure the experiment key matches exactly
  4. Server logs will show: Failed to get feature flag <key>: ... if there's an error