Analytics & Data8 min read

How to Integrate PostHog with Your Headless CMS

Connect PostHog to your content layer so product, growth, and editorial teams can see which pages, authors, campaigns, and content variants lead to signups, activation, and retention.

Published April 29, 2026
01 โ€” Overview

What is PostHog?

PostHog is an open-source product analytics platform for event tracking, session replay, feature flags, experiments, surveys, and product data workflows. Product, engineering, growth, and data teams use it to understand what users do inside websites and apps, then test changes based on real behavior. It competes with tools like Amplitude, Mixpanel, Heap, and feature-flag platforms, while also offering self-hosting for teams that need more control over their analytics stack.


02 โ€” The case for integration

Why integrate PostHog with a headless CMS?

PostHog tells you what users did. Your content layer tells you what they saw. When those systems aren't connected, you're stuck with analytics like page_path = /blog/launch-post and event = signup_clicked, but you can't reliably answer which Sanity document, author, topic, locale, CTA variant, or campaign field produced that behavior.


03 โ€” Architecture

Architecture overview

A typical Sanity and PostHog integration has two flows. First, content editors publish a document in Sanity Studio. That document is written to the Content Lake, and a GROQ-powered webhook or Sanity Function runs only for the document types you care about, such as article, landingPage, docsPage, or campaign. The handler receives the mutation event, fetches the published document from the Content Lake with GROQ, joins references like author or category, and sends a server-side event to PostHog using the PostHog Node SDK or Capture API. For example, it can capture content_published with properties such as content_id, slug, content_type, locale, author, campaign, and experiment_id.


04 โ€” Use cases

Common use cases

๐Ÿ“ˆ

Content performance by source document

Attach Sanity document IDs, slugs, authors, topics, and locales to PostHog events so teams can compare signup, activation, and retention by content record instead of URL alone.

๐Ÿงช

Experiment reporting for content variants

Model headline, CTA, or page variants in Sanity, serve the selected variant in your app, and capture experiment_id and variant in PostHog for conversion analysis.

๐Ÿšฉ

Feature flag controlled content

Use PostHog feature flags to decide which Sanity content variant to show, then record which version each user saw and what they did next.

๐ŸŽฅ

Session replay with content context

Send content_id, slug, locale, and campaign fields to PostHog so teams can filter replays to sessions that viewed a specific article, docs page, or launch campaign.


05 โ€” Implementation

Step-by-step integration

  1. 1

    Set up PostHog

    Create a PostHog project, choose your host region or self-hosted URL, and copy the project API key from Project settings. Install posthog-js for frontend events and posthog-node for server-side capture events.

  2. 2

    Model analytics fields in Sanity Studio

    Add fields that analytics teams can trust, such as analyticsKey, campaignId, experimentId, canonicalPath, locale, and contentType. If the content has authors, topics, or products, model them as references so GROQ can join them into PostHog event properties.

  3. 3

    Create a publish trigger

    Use a Sanity webhook with a GROQ filter such as _type in ['article', 'landingPage', 'docsPage'] and !(_id in path('drafts.**')). For server-side logic inside Sanity, use Functions to react to content mutations without running separate infrastructure.

  4. 4

    Fetch the exact content fields with GROQ

    In the webhook handler or Function, use @sanity/client to fetch the published document by ID. Project only the fields PostHog needs, including joined references like author->name and category->slug.current.

  5. 5

    Send events to PostHog

    Use the PostHog Node SDK or Capture API to capture events such as content_published, content_updated, and content_unpublished. Use consistent property names, because PostHog breakdowns and funnels depend on clean event data.

  6. 6

    Test frontend tracking

    Initialize posthog-js in your app, query Sanity for the page, and include Sanity metadata on $pageview and CTA events. Confirm the events in PostHog Live Events, then build dashboards for content conversion, funnel drop-off, and experiment results.



07 โ€” Why Sanity

How Sanity + PostHog works

Build your PostHog integration on Sanity

Sanity gives you the structured content foundation, real-time event system, and flexible APIs to connect PostHog data with the content your users actually experience.

Start building free โ†’

08 โ€” Comparison

CMS approaches to PostHog

CapabilityTraditional CMSSanity
Content metadata for analytics eventsSchema fields like analyticsKey, campaignId, experimentId, and locale live with the content and can be sent to PostHog as typed JSON.
Publish-time sync to PostHogGROQ-powered webhooks can trigger only for the published documents you choose, and Functions can run the server-side PostHog call.
Field-level control over event payloadsGROQ can select exact fields, join references, and shape the payload before sending it to PostHog.
A/B test content supportDevelopers can model variants in schema-as-code, editors can work in Sanity Studio, and apps can send experiment_id and variant to PostHog.
Setup trade-offsRequires clear schema design and event naming decisions, but gives you precise control over the content data PostHog receives.

09 โ€” Next steps

Keep building

Explore related integrations to complete your content stack.

Ready to try Sanity?

See how Sanity's Content Operating System powers integrations with PostHog and 200+ other tools.