How to Integrate LogRocket with Your Headless CMS
Connect LogRocket to structured content so every replay, error, network trace, and rage click can be tied back to the exact article, product, locale, or campaign a user saw.
What is LogRocket?
LogRocket is a session replay and frontend observability platform for web and mobile teams. It records user sessions, JavaScript errors, console logs, network requests, performance data, and product behavior so engineering, product, and support teams can reproduce issues with context. Teams use it when a stack trace alone isn't enough, especially for bugs that depend on user state, browser behavior, content, or timing.
Why integrate LogRocket with a headless CMS?
A replay that says a user clicked a broken CTA on `/summer-sale` helps. A replay that says they clicked `cta.primary` on landing page `summer-sale-2026`, locale `en-US`, content release `spring-launch`, and variant `B` helps a lot more. When LogRocket is connected to your headless CMS, session data can include the structured content context behind the page, not just the URL that happened to render it.
For Monitoring & Observability teams, this solves a common gap. Frontend tools capture what happened in the browser, while content systems know what the user was actually reading, buying, comparing, or trying to submit. With structured content in Sanity's Content Lake, you can pass LogRocket exact fields like `_id`, `_type`, `slug`, `locale`, `campaignId`, `author`, and `releaseId`. GROQ selects only the fields LogRocket needs, and webhooks or Functions react when content changes so your app isn't relying on stale lookup tables.
The disconnected version is messy. Engineers inspect a replay, copy the URL, search the content system manually, ask an editor whether the page changed that day, and then guess which version the user saw. That can turn a 10-minute bug report into a 2-hour investigation. The trade-off is that LogRocket's custom event capture runs in the client SDK, so most teams use Sanity webhooks or Functions to prepare content context, then send it to LogRocket from the browser when the user views or interacts with that content.
Architecture overview
A typical Sanity and LogRocket integration starts with structured content in the Content Lake. You model pages, products, campaigns, help articles, or other content types in Sanity Studio, including fields that matter for observability, such as slug, locale, campaign ID, experiment key, release ID, and owner team. When an editor publishes or updates content, a Sanity webhook fires. You can filter the webhook with GROQ so it only runs for types LogRocket should know about, for example `_type in ["page", "product", "article"]`. The webhook can call a Sanity Function, or the Function can handle the mutation directly. Inside that server-side step, `@sanity/client` fetches the full content context with GROQ, including referenced data like author, category, or campaign. From there, the Function writes a small content-context payload to your app, cache, or API route. When the end user loads the page, your frontend initializes the LogRocket browser SDK with `LogRocket.init("org/app")`, then calls `LogRocket.track("Sanity content viewed", payload)` and, when appropriate, `LogRocket.identify(userId, traits)`. LogRocket attaches those custom events and traits to the user's replay, so engineers can filter sessions by content ID, content type, locale, campaign, or release. Functions keep the server-side processing close to the content event, with no separate queue or cron job to run. Webhooks are a good fit when you already have middleware or an existing observability service. Either way, GROQ keeps the payload small and specific, instead of sending full documents or rendered HTML.
Common use cases
Replay bugs by content ID
Attach Sanity document IDs and slugs to LogRocket sessions so engineers can filter replays for one article, product page, or campaign.
Connect frontend errors to publish events
When JavaScript errors spike after a content release, compare LogRocket sessions against the Sanity release ID, locale, and content type.
Debug content-driven experiments
Track variant keys from Sanity in LogRocket so product teams can replay sessions for variant A, variant B, or a specific campaign audience.
Give support better session context
Let support teams see the exact help article, onboarding step, or pricing page a customer viewed before opening a ticket.
Step-by-step integration
- 1
Set up LogRocket
Create a LogRocket app, copy the app ID in the `org/app` format, and install the browser SDK with `npm install logrocket`. If you use React, add `@logrocket/react` for component tracking. LogRocket's browser app ID is public client config, not a secret. Create an API token only if your plan and workflow require reporting or export access.
- 2
Initialize LogRocket in your frontend
Call `LogRocket.init(process.env.NEXT_PUBLIC_LOGROCKET_APP_ID)` once in your client app. If users sign in, call `LogRocket.identify(user.id, { email, plan })` after authentication so sessions can be connected to account-level issues.
- 3
Model observability fields in Sanity Studio
Add fields that help investigations, such as `slug`, `locale`, `campaignId`, `experimentKey`, `ownerTeam`, and `supportTier`. Keep these as typed fields in your schema so they're queryable with GROQ and safe to pass into LogRocket events.
- 4
Create the content-change trigger
Add a Sanity webhook or Function for publish and update events. Use a GROQ filter like `_type in ["page", "product", "article"]` so you don't process unrelated documents such as internal notes or reusable labels.
- 5
Fetch the exact payload with GROQ
In your webhook handler or Function, use `@sanity/client` to fetch the changed document and any referenced fields LogRocket should receive. Avoid sending full Portable Text bodies, draft-only fields, or PII. A 10-field payload is easier to search than a 200-field document.
- 6
Send content context to LogRocket and test
Render the content context into the page or fetch it from your app API, then call `LogRocket.track("Sanity content viewed", payload)` in the browser. Test by publishing a page in Sanity Studio, opening it in a browser, triggering a session in LogRocket, and filtering sessions by the Sanity `_id` or slug.
Code example
import {createClient} from '@sanity/client'
const sanity = createClient({
projectId: process.env.SANITY_PROJECT_ID!,
dataset: process.env.SANITY_DATASET!,
apiVersion: '2025-02-19',
token: process.env.SANITY_READ_TOKEN,
useCdn: false,
})
export async function POST(req: Request) {
const body = await req.json()
const id = body._id || body.ids?.updated?.[0] || body.ids?.created?.[0]
const content = await sanity.fetch(
`*[_id == $id][0]{
_id, _type, title, "slug": slug.current,
locale, campaignId, experimentKey,
"author": author->name
}`,
{id}
)
await fetch(`${process.env.SITE_URL}/api/content-context`, {
method: 'POST',
headers: {
'content-type': 'application/json',
authorization: `Bearer ${process.env.INTERNAL_TOKEN}`,
},
body: JSON.stringify(content),
})
return Response.json({ok: true})
}
// Client component on the rendered page
'use client'
import {useEffect} from 'react'
import LogRocket from 'logrocket'
LogRocket.init(process.env.NEXT_PUBLIC_LOGROCKET_APP_ID!)
export function TrackContentView({content}: {content: Record<string, unknown>}) {
useEffect(() => {
LogRocket.track('Sanity content viewed', content)
}, [content])
return null
}How Sanity + LogRocket works
Build your LogRocket integration on Sanity
Sanity gives you the structured content foundation, real-time event system, and flexible APIs to connect LogRocket sessions to the exact content your users saw.
Start building free โCMS approaches to LogRocket
| Capability | Traditional CMS | Sanity |
|---|---|---|
| Session context by content object | Often limited to URL, page title, or rendered HTML, which makes it harder to identify the exact source field behind a replay. | Content Lake documents are structured JSON, and GROQ can return the exact content ID, slug, locale, campaign, and referenced fields for LogRocket. |
| Publish-aware observability | Teams often compare LogRocket timelines with editorial calendars by hand after an error spike. | Webhooks and Functions can react to publish, update, and delete events, then prepare LogRocket-ready context without separate infrastructure. |
| Payload control | Rendered pages can include too much markup and too little structured meaning for useful LogRocket filters. | GROQ projections return small, purpose-built payloads, including joins across references in one query. |
| Experiment and campaign debugging | Variant data may live in templates, plugins, or analytics tools, so LogRocket sessions don't always show which content variant rendered. | Experiment keys, campaign IDs, and release data can be modeled in schema and sent to LogRocket as typed session events. |
| Trade-offs and setup effort | Fast to start if the site already exists, but content-level observability usually needs custom theme code. | You still need to design the event payload and add client-side LogRocket tracking, but Functions, webhooks, and GROQ reduce the moving parts. |
Keep building
Explore related integrations to complete your content stack.
Sanity + Sentry
Connect frontend and backend errors to Sanity document IDs, release data, and content types for faster triage.
Sanity + Datadog
Send content publish events into Datadog so infrastructure metrics can be compared with editorial and campaign changes.
Sanity + New Relic
Track application performance alongside Sanity-driven content releases, locales, and high-traffic pages.