Skip to content

New Relic browser error tracking

How it works

One New Relic Browser app receives errors from every deployment (production, staging, and preview branches). Each error is tagged with deploy_env and deploy_branch so you can filter by environment or branch. Source maps are generated and uploaded only for production (main), so only production errors get unminified stack traces; staging and previews still report errors but with minified stacks.

1. Who builds what

Builder When Source maps? What happens
Cloudflare Every push (all branches) No Runs npm run build:cloudflare → sets deploy env from CF_PAGES_BRANCHnext build (no maps). Deploys the app.
GitHub CI On push to main (or similar) Yes Sets UPLOAD_SOURCEMAPS=1 and NR secrets → npm run build → generates maps, postbuild uploads them to New Relic and deletes local .map files. Does not deploy.

Cloudflare never generates or uploads source maps; it only builds and deploys. GitHub CI is the only place that produces and uploads maps, and only for the production build.

2. How deploy_env and deploy_branch get set

On Cloudflare, the build command is npm run build:cloudflare. That runs:

  1. scripts/set-build-env.sh
    Cloudflare injects CF_PAGES_BRANCH (e.g. main, staging, feat/xyz) into the build environment. The script reads it and exports:
  2. NEXT_PUBLIC_DEPLOY_BRANCH = CF_PAGES_BRANCH (the actual branch name).
  3. NEXT_PUBLIC_DEPLOY_ENV = production if branch is main, staging if branch is staging, otherwise preview.

  4. npm run build
    Next.js bakes NEXT_PUBLIC_* into the client bundle. So every page load has the correct branch and env for that deployment.

  5. At runtime
    When the app loads in the browser, instrumentation-client.ts runs. After the New Relic agent initializes, it calls newrelic.setCustomAttribute('deploy_env', ...) and setCustomAttribute('deploy_branch', ...) with those baked-in values. Every subsequent error (and other events) sent to New Relic carry these attributes.

So you don’t configure env per branch in Cloudflare; one build command works for main, staging, and every preview branch.

3. How errors are reported

  • Unhandled errors: window.onerror and window.onunhandledrejection are wired in instrumentation-client.ts to call reportError, which calls newrelic.noticeError(error) when the agent is loaded.
  • Handled errors: You can call window.ErrorHandler(error) or ErrorHandler(error) from anywhere; it reports to New Relic with the same attributes.
  • All of these events include the current deploy_env and deploy_branch set at agent init.

4. How source maps work (production only)

  • Next.js: In next.config.ts, productionBrowserSourceMaps is true only when UPLOAD_SOURCEMAPS=1. Cloudflare does not set that, so its builds don’t emit .map files.
  • GitHub CI: A job (e.g. on push to main) sets UPLOAD_SOURCEMAPS=1, NR_APPLICATION_ID, NR_API_KEY, and BASE_URL (your production URL), then runs npm run build. The build generates .map files; the postbuild script uploads each to New Relic (using the production BASE_URL for the JS URLs) and then deletes them locally. So only production gets unminified stack traces in New Relic; staging and preview stacks stay minified.

Cloudflare Pages

Full setup steps (Story Desk SSG + New Relic + PostHog) are in docs/cloudflare-setup.md.

  • Build command: npm run build:cloudflare
    This runs scripts/set-build-env.sh (which sets NEXT_PUBLIC_DEPLOY_BRANCH and NEXT_PUBLIC_DEPLOY_ENV from CF_PAGES_BRANCH) then npm run build. No per-branch env configuration needed.
  • Source maps on Cloudflare (optional): To get source maps for the Cloudflare-built deployment, set UPLOAD_SOURCEMAPS=1, NR_APPLICATION_ID, NR_API_KEY, and BASE_URL (production origin) in Cloudflare Pages env for the production branch. Then this build generates maps, postbuild uploads them to New Relic and deletes them locally. If you do not set these, Cloudflare builds produce no .map files and the upload script logs "No .js.map files"; only GitHub CI (or another build with these env vars) can upload maps.

GitHub CI (source maps for production only)

Run a job on push to main (or after production deploy) that:

  • Sets UPLOAD_SOURCEMAPS=1, NR_APPLICATION_ID, NR_API_KEY (must be a User API key from New Relic, not the license key—otherwise upload returns Unauthorized), BASE_URL=<production URL> (e.g. from secrets).
  • Runs npm run build. Postbuild uploads source maps to New Relic and removes local .map files.

Staging and preview branches do not need this job; they report errors with minified stacks but tagged by branch/env.

Filtering errors in New Relic

All deployments (main, staging, previews) report to the same Browser app. Use custom attributes:

  • deploy_env: production (main) | staging | preview
  • deploy_branch: Git branch name (e.g. main, staging, feat/xyz)

Filter or group by these in the New Relic UI to see errors by environment or branch.