Buttercms Troubleshooting: Common Issues and Fixes | OpsBlu Docs

Buttercms Troubleshooting: Common Issues and Fixes

Debug analytics issues on ButterCMS — headless API delivery timing, framework integration gaps, preview mode interference, and webhook-driven rebuild...

ButterCMS is a headless CMS that delivers content via API. Since ButterCMS has no built-in frontend, analytics issues are always about the integration between ButterCMS's content API and whatever framework renders your site (Next.js, Gatsby, Nuxt, etc.). The CMS itself never serves HTML to visitors — your frontend does.

ButterCMS-Specific Debugging Approach

The key distinction with ButterCMS is that tracking problems live in your frontend codebase, not in ButterCMS itself. ButterCMS only supplies content data; your framework handles rendering and script injection.

Verify API Response vs. Rendered Output

First, confirm ButterCMS is delivering content correctly, then check if your frontend renders the tracking code:

// Check if ButterCMS content fields containing analytics config are loaded
// In browser console on your site:
console.log('Page meta:', document.querySelector('meta[name="butter-page-type"]')?.content || 'No Butter meta');

// If you store tracking IDs or custom scripts in ButterCMS fields:
fetch('https://api.buttercms.com/v2/pages/*/your-page-slug/?auth_token=YOUR_TOKEN')
  .then(r => r.json())
  .then(data => {
    console.log('ButterCMS fields:', Object.keys(data.data.fields));
    const fields = data.data.fields;
    console.log('Has tracking code:', !!fields.tracking_code || !!fields.head_scripts);
  });

Check Framework-Level Script Injection

Since ButterCMS is headless, your analytics implementation depends on your frontend framework:

// For Next.js + ButterCMS: check if Script component loaded
document.querySelectorAll('script[data-nscript]').forEach(s => {
  console.log('Next.js script:', s.src || s.textContent.substring(0, 50), '| strategy:', s.dataset.nscript);
});

// For Gatsby + ButterCMS: check gatsby-plugin-google-gtag
console.log('Gatsby gtag:', typeof window.gtag === 'function' ? 'loaded' : 'missing');

// For Nuxt + ButterCMS: check module injection
console.log('Nuxt GA:', window.$nuxt?.$ga ? 'loaded' : 'missing');

Most Common ButterCMS Analytics Issues

1. Static Site Build Missing Dynamic Tracking Code

Symptoms: Analytics works in development but not on the deployed site. Tracking code present locally but absent from the built output.

Root cause: If you store analytics snippets in ButterCMS content fields and your site is statically generated (Gatsby, Next.js static export), the tracking code is fetched at build time. If the ButterCMS API was unreachable during the build, the field comes back empty.

Diagnosis:

# Check your build logs for ButterCMS API failures
grep -i "buttercms\|butter\|ECONNREFUSED\|timeout\|429" build.log

# Verify the API returns the expected data
curl -s "https://api.buttercms.com/v2/pages/site-settings/global/?auth_token=YOUR_TOKEN" \
  | python3 -m json.tool | grep tracking

Fix: Add fallback tracking code in your frontend template that activates when the ButterCMS field is empty:

// Next.js example with ButterCMS fallback
import Script from 'next/script';

export default function Layout({ butterSettings, children }) {
  const trackingId = butterSettings?.tracking_id || process.env.NEXT_PUBLIC_GA_ID;

  return (
    <>
      {trackingId && (
        <Script
          src={`https://www.googletagmanager.com/gtag/js?id=${trackingId}`}
          strategy="afterInteractive"
        />
      )}
      {children}
    </>
  );
}

2. Preview Mode Firing Production Analytics

Symptoms: Pageview spikes during content editing. Preview URLs show up in analytics data.

Root cause: ButterCMS preview mode loads your frontend with draft content, but your analytics code still fires against the production GA property.

Fix: Detect ButterCMS preview mode and suppress analytics:

// ButterCMS preview is indicated by a preview parameter
const isButterPreview = new URLSearchParams(window.location.search).has('preview') ||
  document.cookie.includes('butter_preview');

if (isButterPreview) {
  window['ga-disable-G-XXXXXXX'] = true;
  console.log('ButterCMS preview mode — analytics disabled');
}

3. Webhook-Triggered Rebuilds Delayed

Symptoms: Content editors update a ButterCMS page, but the live site still shows old analytics configuration for minutes or hours.

Root cause: When using static site generation, ButterCMS sends a webhook to trigger a rebuild. The rebuild and deployment pipeline takes time, and until it completes, the old build is served.

Fix: For time-sensitive analytics changes, use ISR (Incremental Static Regeneration) in Next.js or on-demand revalidation instead of full static builds:

// Next.js API route for ButterCMS webhook
export default async function handler(req, res) {
  if (req.body.data?.page_type === 'site-settings') {
    await res.revalidate('/');
    await res.revalidate('/about');
    return res.json({ revalidated: true });
  }
  return res.json({ revalidated: false });
}

4. Multi-Language Content Splitting Analytics

Symptoms: Analytics data is fragmented across locales. Same page shows different tracking IDs or configurations per language.

Root cause: ButterCMS supports localized content fields. If your tracking configuration is stored in a localized field, each locale may have different (or empty) analytics settings.

Fix: Store analytics configuration in a non-localized ButterCMS field, or ensure all locales have identical tracking IDs:

// Fetch global (non-localized) settings separately
const globalSettings = await butter.page.retrieve('site-settings', 'global');
const trackingId = globalSettings.data.fields.tracking_id;
// Use this for all locales regardless of current language

5. Client-Side Routing Not Tracked After Initial Load

Symptoms: First pageview registers but SPA-style navigation between ButterCMS-powered pages does not.

Root cause: Frameworks like Next.js and Nuxt use client-side routing. After the initial load, navigation between ButterCMS pages happens without a full page reload.

Fix: Hook into your framework's router:

// Next.js App Router
'use client';
import { usePathname } from 'next/navigation';
import { useEffect } from 'react';

export function ButterAnalytics() {
  const pathname = usePathname();

  useEffect(() => {
    gtag('event', 'page_view', {
      page_path: pathname,
      page_title: document.title
    });
  }, [pathname]);

  return null;
}

Environment Considerations

  • No server to manage: ButterCMS is SaaS API-only. All infrastructure issues are on your frontend hosting side
  • API rate limits: ButterCMS has rate limits (varies by plan). During static builds with many pages, API failures can cause missing content including analytics config
  • CDN caching: Your hosting platform's CDN (Vercel Edge, Netlify CDN, Cloudflare) caches the built output. Analytics changes propagate only after a rebuild and CDN invalidation
  • Staging vs production: ButterCMS draft/published content model means preview environments may have different field values than production

Performance Issues

Tracking Issues

  • Events Not Firing - Debug build-time API failures, preview mode leakage, and client-side routing gaps