Keystonejs Analytics Integrations: Setup Guide | OpsBlu Docs

Keystonejs Analytics Integrations: Setup Guide

Integrate GA4, GTM, and Meta Pixel with KeystoneJS using its GraphQL API, Next.js frontend, and custom schema extensions.

KeystoneJS is an open-source headless CMS and application framework built on Node.js, Prisma ORM, and GraphQL. It provides a GraphQL API for content delivery and an auto-generated Admin UI. Since KeystoneJS is a backend framework (not a frontend), analytics integration happens in whatever frontend you build to consume its GraphQL API.

Integration Architecture

KeystoneJS is a backend API server:

  1. Frontend Framework -- You build the frontend (typically Next.js, Remix, or Astro). All tracking scripts load in your frontend code, not in KeystoneJS.
  2. GraphQL API -- KeystoneJS auto-generates a GraphQL schema from your Keystone schema definition. Query content lists and items to build your data layer.
  3. Session & Auth -- KeystoneJS handles authentication. You can pass auth context to your data layer (logged-in state, user role) via the GraphQL API or session cookies.
  4. Hooks & Access Control -- Keystone's resolveInput, afterOperation, and validateInput hooks can trigger server-side analytics events (e.g., logging content creation events to GA4 Measurement Protocol).

Available Integrations

Analytics Platforms

Google Analytics 4

  • Frontend gtag.js integration
  • GTM-based GA4 with KeystoneJS GraphQL data layer
  • Server-side Measurement Protocol via Keystone hooks

Tag Management

Google Tag Manager

  • Frontend app shell integration
  • SPA route-change tracking

Marketing Pixels

Meta Pixel

  • Via GTM container (recommended)
  • Server-side Conversions API via Keystone afterOperation hooks

Next.js + KeystoneJS Example

For a Next.js frontend consuming KeystoneJS's GraphQL API:

// app/posts/[slug]/page.tsx
import { keystoneClient } from '@/lib/keystone';
import { gql } from 'graphql-request';

const QUERY = gql`
  query Post($slug: String!) {
    post(where: { slug: $slug }) {
      title
      slug
      status
      author { name }
      tags { name }
      category { name }
      publishDate
    }
  }
`;

export default async function Post({ params }) {
  const { post } = await keystoneClient.request(QUERY, { slug: params.slug });

  return (
    <>
      <script
        dangerouslySetInnerHTML={{
          __html: `
            window.dataLayer = window.dataLayer || [];
            window.dataLayer.push({
              event: 'virtual_pageview',
              content_type: 'post',
              page_title: ${JSON.stringify(post.title)},
              author: ${JSON.stringify(post.author?.name || '')},
              category: ${JSON.stringify(post.category?.name || '')},
              tags: ${JSON.stringify(post.tags?.map(t => t.name).join(',') || '')},
              status: '${post.status}',
              publish_date: '${post.publishDate || ''}'
            });
          `,
        }}
      />
      <article>{/* render post */}</article>
    </>
  );
}

Server-Side Analytics via Keystone Hooks

KeystoneJS's hook system enables server-side event tracking. For example, send a GA4 event when content is published:

// keystone.ts (schema definition)
import { list } from '@keystone-6/core';
import { text, timestamp, select } from '@keystone-6/core/fields';

export default config({
  lists: {
    Post: list({
      fields: {
        title: text({ validation: { isRequired: true } }),
        status: select({ options: [
          { label: 'Draft', value: 'draft' },
          { label: 'Published', value: 'published' },
        ]}),
      },
      hooks: {
        afterOperation: async ({ operation, item, originalItem }) => {
          if (operation === 'update'
            && item.status === 'published'
            && originalItem?.status === 'draft') {
            // Send server-side event via GA4 Measurement Protocol
            await fetch(`https://www.google-analytics.com/mp/collect?measurement_id=G-XXXX&api_secret=SECRET`, {
              method: 'POST',
              body: JSON.stringify({
                client_id: 'server',
                events: [{ name: 'content_published', params: { content_id: item.id, title: item.title } }],
              }),
            });
          }
        },
      },
    }),
  },
});

Platform Limitations

No built-in frontend. KeystoneJS is a backend framework. The Admin UI is for content management only and is not a public-facing website. All frontend analytics are your responsibility.

GraphQL schema changes. Modifying your Keystone schema (adding/removing fields, renaming lists) changes the GraphQL API. Data layer queries in your frontend must be updated when the schema changes. Use TypeScript codegen (@graphql-codegen) to catch mismatches at build time.

Session-based auth complexity. KeystoneJS uses session cookies for authentication. If your data layer includes user role or authentication state, ensure you're reading session data correctly across SSR and client-side rendering.

Prisma ORM performance. KeystoneJS uses Prisma for database access. Complex GraphQL queries with many relations can generate slow SQL. Keep data layer queries simple -- request only the fields needed for analytics.

Performance Considerations

  • GraphQL efficiency. Request only analytics-relevant fields in your data layer queries. KeystoneJS's auto-generated GraphQL schema includes all fields, but you should project only what you need.
  • SSG/ISR. Pre-render pages at build time or via ISR to eliminate runtime GraphQL queries. Data layer values are baked into the HTML.
  • Admin UI isolation. The Keystone Admin UI at /admin should be excluded from analytics tracking. It is a separate React application not intended for public traffic.
  1. Add GTM to frontend app shell -- Single container for all tracking
  2. Build GraphQL data layer queries -- Map KeystoneJS lists and fields to data layer variables
  3. Implement SPA route tracking -- Virtual pageview events on navigation
  4. Configure GA4 via GTM -- Content groups from KeystoneJS list types
  5. Add server-side hooks -- GA4 Measurement Protocol for content lifecycle events

Next Steps

For general integration concepts, see the integrations overview.