Analytics & Data8 min read

How to Integrate FullStory with Your Headless CMS

Connect FullStory to structured content so product, UX, and marketing teams can replay sessions, analyze behavior, and tie every click back to the exact content users saw.

Published April 29, 2026
01 โ€” Overview

What is FullStory?

FullStory is a digital experience intelligence platform that records user sessions, captures product analytics events, and helps teams investigate friction such as rage clicks, dead clicks, JavaScript errors, and drop-offs. Product, UX, support, engineering, and growth teams use it to understand what happened in a session without relying only on aggregate dashboards.


02 โ€” The case for integration

Why integrate FullStory with a headless CMS?

FullStory shows you what users did. Your headless CMS category system tells you what they were looking at. When those two systems are disconnected, teams end up comparing URLs, campaign spreadsheets, release notes, and analytics exports by hand. That works for one landing page. It breaks when you have 800 product pages, 12 locales, rotating campaigns, and weekly content releases.

Connecting FullStory to structured content gives every captured session more context. Instead of only searching for sessions on `/products/running-shoe`, you can filter or analyze behavior by content type, product category, locale, authoring team, campaign ID, release ID, or experiment variant. That makes questions much easier to answer, like, "Did users rage-click more on the Spanish pricing page after Friday's copy update?" or "Which sessions saw the new comparison table before conversion dropped?"

A structured back end matters here. With Sanity's AI Content Operating System, content in the Content Lake is typed JSON, so you don't need to scrape HTML or parse page blobs to send useful metadata to FullStory. GROQ selects exactly the fields FullStory needs, webhooks trigger when content is published, updated, or deleted, and Functions can run sync logic server-side without a separate queue or worker. The trade-off is that you'll still need to decide which content fields belong in FullStory. Sending every field can create noisy analytics and expose data you don't want in a behavior tool.


03 โ€” Architecture

Architecture overview

A typical Sanity and FullStory integration has two paths: a content event path and a user-session path. On the content side, editors publish or update a document in Sanity Studio. The mutation lands in the Content Lake, then a Sanity webhook fires on the publish event. A Sanity Function, webhook listener, or small middleware endpoint receives the document ID, runs a GROQ query to fetch the fields FullStory needs, and calls FullStory's Events API to record a content lifecycle event such as `Sanity Content Published`. On the user-session side, your frontend loads FullStory through its browser SDK, usually `@fullstory/browser` or the FullStory snippet. When a user views a page, your app passes content metadata from Sanity to FullStory as custom event properties or user/session variables, such as `contentId`, `contentType`, `slug`, `locale`, `campaignId`, and `experimentVariant`. FullStory then records the session replay, clicks, errors, page views, and custom events with that content context attached. The end user doesn't see the integration. They just visit the site or app. Behind the scenes, Sanity provides the structured content, GROQ controls the payload, webhooks or Functions handle publish-time events, and FullStory captures the behavioral record that product and UX teams can search later.


04 โ€” Use cases

Common use cases

๐Ÿ”Ž

Find sessions by content metadata

Search FullStory sessions by Sanity fields like content type, campaign ID, locale, product category, or experiment variant instead of relying only on URLs.

๐Ÿ“‰

Debug conversion drops after publishing

Send content publish events to FullStory so teams can compare session behavior before and after a pricing page, onboarding flow, or product detail page changed.

๐Ÿ˜ค

Investigate rage clicks on specific content

Filter FullStory rage-click and dead-click sessions to a specific Sanity document, such as a help article, landing page, or product comparison block.

๐Ÿงช

Analyze content experiments

Pass Sanity-controlled variant IDs into FullStory events so UX and growth teams can replay sessions for each copy, layout, or CTA version.


05 โ€” Implementation

Step-by-step integration

  1. 1

    Set up FullStory

    Create a FullStory account, get your Org ID from FullStory settings, and install the browser SDK with `npm install @fullstory/browser`. Initialize it in your app with `init({ orgId: 'YOUR_ORG_ID' })`, then confirm sessions appear in FullStory. If you're sending server-side content events, create an API key in FullStory settings and keep it in server-only environment variables.

  2. 2

    Model analytics-ready content in Sanity Studio

    Add fields that help explain user behavior, not just fields that render the page. For a landing page, that might include `title`, `slug`, `locale`, `campaignId`, `audience`, `experimentVariant`, `primaryCta`, and references to related products or categories.

  3. 3

    Query only the fields FullStory needs

    Write a GROQ query that fetches the document ID, type, slug, locale, campaign fields, and referenced category or product names. Keep private editorial notes, drafts, approval comments, and internal planning fields out of the FullStory payload.

  4. 4

    Create the sync mechanism

    Use a Sanity webhook filtered to publish mutations, or use a Sanity Function if you want the logic to run inside Sanity's event system. The handler receives the changed document ID, fetches the current published document from the Content Lake, and sends a `Sanity Content Published` event to FullStory's Events API.

  5. 5

    Add FullStory tracking to the frontend

    In your website or app, initialize FullStory and send a page event when Sanity content renders. Include fields such as `contentId`, `contentType`, `slug`, `locale`, and `campaignId`, so FullStory sessions can be filtered by the content users actually saw.

  6. 6

    Test with one document and one session

    Publish a test page in Sanity Studio, check that your webhook or Function sends the FullStory event, visit the page in a test browser, and confirm the session includes the expected content metadata. Then test an update, an unpublished page, and a locale variant before rolling it out to every content type.



07 โ€” Why Sanity

How Sanity + FullStory works

Build your FullStory integration on Sanity

Sanity gives you the structured content foundation, real-time event system, and flexible APIs you need to connect content changes and user behavior in FullStory.

Start building free โ†’

08 โ€” Comparison

CMS approaches to FullStory

CapabilityTraditional CMSSanity
Content metadata for session replayOften tied to rendered pages, templates, or plugins, so analytics teams may rely on URL patterns and manual naming rules.Content is structured in the Content Lake as typed JSON, making fields like campaign, locale, variant, and category ready for FullStory events.
Publish-time event trackingUsually handled with plugins, scheduled exports, or custom server code that may not fire consistently across content types.Webhooks and Functions can trigger on mutations, fetch the final published document, and send the right event payload to FullStory.
Field-level controlTeams often send page-level data because field-level content can be hard to access outside the rendering layer.GROQ can fetch, filter, project, and join referenced content in one query, so FullStory receives a focused payload.
Experiment and campaign contextCampaign metadata may live in spreadsheets, tag managers, or page naming conventions.Campaign IDs, audience fields, release data, and variant references can live in the schema and travel with the content to FullStory.
Frontend tracking setupUsually depends on template access, plugin compatibility, and whether developers can add custom FullStory calls where content renders.Frontend apps can query Sanity content and pass the same document metadata into FullStory browser events on page view.
Operational trade-offsLower initial setup if a plugin exists, but less control over data shape and event quality.More planning up front for schema design and field governance, but cleaner analytics data once the integration is running.

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 FullStory and 200+ other tools.