add-analytics
Skill50 starsChanged 20 days agoApache-2.0View on GitHub
Add Google Analytics (GA4) to an existing Next.js project. Includes RGPD cookie consent banner.
- Reads credentials
3 other projects use a version of this.
Adopted by
Most recently taken up by
- sesori-ai/sesori_apps_monorepotheir own version, first seen Nov 8, 2026
- flavien-ia/hypervibe-craftword for word, first seen Oct 25, 2026
- jeftekhari/google-analyticstheir own version, first seen Feb 1, 2026
Other versions3 projects use a version of this.
Word for word · 1
- flavien-ia/hypervibe-craft★ 50100% same
Edited · 0
None found.
Wrote their own version · 2
- sesori-ai/sesori_apps_monorepo★ 140same name
- jeftekhari/google-analytics★ 2same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository89 other files it gives its agents.
- accessibilitySkill
- add-2faSkill
- add-agent-dashboardSkill
- add-aiSkill
- add-authSkill
- add-automationSkill
- add-backup-dbSkill
- add-collabSkill
- add-cronSkill
- add-dark-modeSkill
- add-dbSkill
- add-domainSkill
- add-emailSkill
- add-github-authSkill
- add-google-authSkill
- add-i18nSkill
- _add-keyringSkill
- add-mapSkill
- add-notification-centerSkill
- add-push-notificationSkill
- add-pwaSkill
- add-roleSkill
- add-routineSkill
- add-storageSkill
- add-stripeSkill
- add-testSkill
- bootstrapSkill
- _check-depsSkill
- cleanSkill
- _collect-secretSkill
- _convert-to-turborepoSkill
- _create-agentSkill
- _create-cloudflare-workerSkill
- _create-contact-pageSkill
- _create-render-workerSkill
- _create-routineSkill
- _create-workflowSkill
- delete-projectSkill
- _detect-project-rootSkill
- _dns-brevoSkill
- _dns-cloudflareSkill
- _dns-gandiSkill
- _dns-godaddy-manualSkill
- _dns-hostingerSkill
- _dns-infomaniak-manualSkill
- _dns-ionos-manualSkill
- _dns-lwsSkill
- _dns-namecheapSkill
- _dns-ovhSkill
- _dns-porkbunSkill
- _dns-resendSkill
- _dns-squarespace-manualSkill
- eco-auditSkill
- _ensure-aiSkill
- _ensure-vaultSkill
- _generate-secretSkill
- geoSkill
- _get-secretSkill
- gscSkill
- _hash-passwordSkill
- The first 60 shown.
The file
Show its rules and text
We split this skill into the rules it gives an agent
24 rules. About 0 are common, 11 are distinctive, and 13 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈11
Distinctive · estimate
This author's own choices. Worth a look.
13
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 12
Use plain, non-technical business language.
- Distinctive: line 13
When generating user-facing content for the scaffolded project (UI labels, emails, copy), write it in the user's language too.
- Distinctive: line 47
Wait for the answer.
- Very specific: line 65
Read the current GoogleAnalytics.tsx.
- Very specific: line 66
If it is still the old version (no EXCLUDED_PREFIXES and no usePathname), replace its entire contents with the Step 4 component (keeping …
- Very specific: line 67
Follow the "To do after creating the component - offer to broaden the exclusion" block of Step 4 to detect and (on confirmation) add the …
- Very specific: line 82
If NEXT_PUBLIC_APP_URL points to a .vercel.app -> warn the user and offer: (a) do /add-domain first (recommended), (b) continue anyway with …
- Very specific: line 83
If NEXT_PUBLIC_APP_URL points to a custom domain -> continue.
- Very specific: line 139
Create a GoogleAnalytics component (location depends on project structure - e.g.
- Very specific: line 269
Only offer this option if a SessionProvider already wraps the app (otherwise useSession crashes).
- Very specific: line 273
Create a CookieConsent component alongside the GoogleAnalytics component, at src/components/CookieConsent.tsx.
- Distinctive: line 284
Detect the project's i18n state: run in bash
- Very specific: line 298
Look in globals.css or the project's CLAUDE.md for the main accent color
- Very specific: line 322
Add both components to the root layout, before </body>:
- Distinctive: line 356
If the project has i18n: : add the translation key to all message files:
- Very specific: line 363
Place it in the same namespace as the other footer legal links (typically footer.manageCookies).
- Distinctive: line 365
Note: : if the project has no footer yet (rare), skip this step but inform the user - they'll need to add the link manually when they build …
- Distinctive: line 371
Add Google Analytics to the project's RGPD subprocessor registry:
- Distinctive: line 383
Add Google to the list of subprocessors if not already present
- Distinctive: line 385
If the site has i18n, update ALL language files.
- Very specific: line 408
Use AskUserQuestion with two options:
- Distinctive: line 441
If the user says "it is done" -> add to the summary the line "📬 GA4 scheduled email report enabled" + continue to Step 10.
- Very specific: line 442
If the user says "later" -> mention in the summary that the guidance is available by re-running /add-analytics (re-configuration mode).
- Distinctive: line 456
If scheduled email reports were configured in Step 9: remind that the user can manage their reports in GA4 -> Admin -> Scheduled reports
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Add Analytics - Google Analytics (GA4)
Communication
- Detect the user's language from the conversation (the user's own messages, anywhere in the session - not just this invocation: a bare slash command like
/bootstrapcarries no language signal by itself). If nothing in the conversation gives a signal, fall back to the OS locale (node -e "console.log(Intl.DateTimeFormat().resolvedOptions().locale)") before defaulting to English. ALWAYS reply in that language for every user-facing message: questions, progress, confirmations, summaries, errors - including any example text quoted in this skill, which is illustrative and must be translated, never sent verbatim. - Use plain, non-technical business language. Never expose internal script names (*.mjs) or jargon; describe actions in human terms.
- When generating user-facing content for the scaffolded project (UI labels, emails, copy), write it in the user's language too.
- Show progress as a short natural-language checklist (in-progress and done states).
Adds Google Analytics tracking to the current project with RGPD-compliant cookie consent. Can be called by /bootstrap or standalone on an existing project.
Step 0 - Preflight: is Analytics already configured?
First of all, invoke _check-deps analytics to detect whether GA4 is already in place:
result=$(node "${CLAUDE_SKILL_DIR}/../../scripts/check-deps.mjs" analytics)
analytics_ok=$(echo "$result" | node -e "console.log(JSON.parse(require('fs').readFileSync(0,'utf8')).analytics.ok)")
ga_id=$(echo "$result" | node -e "console.log(JSON.parse(require('fs').readFileSync(0,'utf8')).analytics.gaId || '')")If analytics_ok = true -> re-configuration mode
GA4 is already in place (ID: $ga_id). Do NOT recreate the <GoogleAnalytics> and <CookieConsent> components, nor rewrite the layout. Show a menu:
📊 Google Analytics is already in place (ID: $ga_id)
What do you want to do?
- Switch GA property (you created a new GA4 property, or you are migrating to another Google Analytics account) - I just replace the
NEXT_PUBLIC_GA_MEASUREMENT_ID- Reinstall the cookie consent banner (if the component was deleted by accident or is broken)
- Reinstall the GoogleAnalytics component (same thing, if deleted or broken)
- Exclude admin routes / authenticated areas from tracking - so that admin and logged-in client sessions are no longer counted as discovery traffic (fixes the pollution of acquisition stats)
- Set up a regular email report - I guide you through enabling GA4 scheduled reports (you receive your statistics in your inbox every week or every month, without having to open GA4)
- Redo everything from scratch (only useful if the configuration is completely broken - first remove
NEXT_PUBLIC_GA_MEASUREMENT_IDfrom the local.envand theGoogleAnalytics.tsx/CookieConsent.tsxcomponents)- Something else - tell me what you want
Wait for the answer.
Depending on the answer:
| Choice | Action |
| 1 (switch GA_ID) | Ask for the new GA_ID (format G-XXXXXXXXXX). Validate that it starts with G-. Push via _push-env-vars. Remind the user that the change becomes visible in GA4 within 24-48h (tag propagation). |
| 2 (reinstall cookie banner) | Re-run only the "Create CookieConsent banner" section (Step 5 of the nominal flow). Do not touch the rest. |
| 3 (reinstall GoogleAnalytics) | Re-run only the "Create GoogleAnalytics component" section (Step 4 of the nominal flow). |
| 4 (exclude admin / authenticated) | Retrofit the exclusion onto an existing component - see the procedure below. |
| 5 (email report) | Jump straight to Step 9 (guidance for enabling GA4 scheduled reports). |
| 6 (redo everything) | Abort: ask the user to clean up manually, then re-run. |
| 7 (something else) | Ask for details. Do not launch the full flow by default. |
Choice 4 - Retrofit the admin / authenticated exclusion
Locate the existing component (GoogleAnalytics.tsx, often under src/components/ or src/components/shared/) and upgrade it to the Step 4 version:
- Read the current
GoogleAnalytics.tsx. - If it is still the old version (no
EXCLUDED_PREFIXESand nousePathname), replace its entire contents with the Step 4 component (keeping the import path ofNEXT_PUBLIC_GA_MEASUREMENT_IDand the file location). If it already hasEXCLUDED_PREFIXES, do not rewrite it - just adjust the list. - Follow the "To do after creating the component - offer to broaden the exclusion" block of Step 4 to detect and (on confirmation) add the authenticated areas (dashboard, members area, account) to
EXCLUDED_PREFIXES. - Verify:
pnpm tsc --noEmit && pnpm lint. - Remind the user that the effect is immediate on the code side, but that the data already collected in GA4 is not retroactively cleaned (only new admin/client sessions stop being counted).
At the end, jump straight to the final summary.
If analytics_ok = false (not yet configured)
Continue normally to Step 1. This is the initial installation flow.
Step 1 - Prerequisite: final domain
Ideally, run /add-analytics AFTER configuring the final domain via /add-domain. Otherwise the GA4 web data stream will point to the Vercel URL, and you will have to update it later in GA4 (possible but tedious). Before asking for the ID, check:
- If
NEXT_PUBLIC_APP_URLpoints to a.vercel.app-> warn the user and offer: (a) do/add-domainfirst (recommended), (b) continue anyway with the Vercel URL and update the GA4 web data stream later. - If
NEXT_PUBLIC_APP_URLpoints to a custom domain -> continue.
Step 2 - Get the Measurement ID
Teaching rule: the audience is often new to this. Before asking anything, explain the two key concepts the user will run into in Google Analytics (property + measurement ID). Use these definitions as-is (with an analogy):
Before getting the ID, two words to know about Google Analytics:
- A property - this is the "record" of a site in Google Analytics. One site = one property. If you have several sites to track (a portfolio + a shop + a blog), you will have one property per site, all stored together in your Google Analytics account. Analogy: if your Google Analytics account is a binder, each property is a folder that holds the statistics of one specific site.
- The measurement ID (Measurement ID, format
G-XXXXXXXXXX) - this is the unique number of the property. It is the one we will paste into your code so that your site sends its visit data to Google Analytics. Without this ID, Google Analytics does not know that it is your site talking. Analogy: it is like the barcode on the box - it links each recorded visit to the right property (the right site).All you have to do is grab this ID and paste it here. I take care of all the rest.
Then guide the creation, clearly distinguishing the two cases:
Adapt the guide to the site URL: replace <URL_DU_SITE> below with the value of the project's NEXT_PUBLIC_APP_URL (for example https://cool-trattoria.vercel.app or a custom domain if already configured). Also replace <NOM_DU_SITE> with a short name suited to the current project.
If you have never used Google Analytics:
- Go to https://analytics.google.com/
- Click "Start measuring"
- Account name: your name or your company's - it is the global container, you will be able to put several properties in it (one site each) later. Click "Next".
- Property name:
<NOM_DU_SITE>(the name of the site we are configuring now). Click "Next".- The next screens ask you a few things about the context (country, currency, industry category, business size, business objectives). Choose whatever best matches your activity, it has no impact on the tracking itself - it is just to help Google personalize the default reports. Continue all the way through by clicking "Next" on each screen.
- At the "Start collecting data" screen, choose the Web platform (and not Android or iOS - it really is a website that we are tracking).
- In the screen that opens ("Set up data stream"):
- Website URL:
<URL_DU_SITE>- Stream name:
<NOM_DU_SITE>(use the same name as the property, it keeps things simple)- Click "Create and continue"
- A window opens with a snippet of code to install manually. Close this window (cross in the top right) - no need to copy this code, I handle the integration myself.
- You then land on the "Web stream details" screen. That is where the measurement ID appears (format
G-XXXXXXXXXX, toward the top right of the page). Copy it and paste it here.If you already have a Google Analytics account (another site is already tracked in it):
- Go to https://analytics.google.com/
- Menu at the bottom left -> Admin (gear icon)
- "+ Create" button -> choose "Property" (you create a new record for your new site, in your existing account)
- Property name:
<NOM_DU_SITE>. Click "Next".- As with a first-time creation, the next screens ask you a few contextual things (country, currency, industry category, business objectives). Choose whatever best matches, continue with "Next".
- At the stream configuration screen, choose the Web platform.
- Website URL:
<URL_DU_SITE>- Stream name:<NOM_DU_SITE>- then "Create and continue".- Close the window with the code snippet (no need, I handle it).
- On the "Web stream details" screen, copy the measurement ID (
G-XXXXXXXXXX) and paste it here.
Do not proceed until the user provides the ID.
Step 3 - Push env var
Invoke _push-env-vars with:
NEXT_PUBLIC_GA_MEASUREMENT_ID=G-XXXXXXXXXX
The helper writes to .env local AND pushes to Vercel (all 3 environments).
Step 4 - Create GoogleAnalytics component
Create a GoogleAnalytics component (location depends on project structure - e.g. src/components/GoogleAnalytics.tsx or src/components/shared/GoogleAnalytics.tsx):
"use client";
import Script from "next/script";
import { usePathname } from "next/navigation";
import { useEffect, useRef, useState } from "react";
declare global {
interface Window {
gtag?: (...args: unknown[]) => void;
}
}
/**
* Route prefixes excluded from Google Analytics.
* No page whose path starts with one of these prefixes is tracked
* (neither on direct load, nor on internal navigation). By default: the admin.
*
* Add your authenticated routes here if you want to keep them out of the
* acquisition stats (admin/client sessions are not discovery traffic),
* for example: "/dashboard", "/espace-membres", "/compte".
*/
const EXCLUDED_PREFIXES = ["/admin"];
function isExcludedPath(pathname: string | null) {
if (!pathname) return false;
return EXCLUDED_PREFIXES.some(
(prefix) => pathname === prefix || pathname.startsWith(`${prefix}/`),
);
}
/**
* Sends a `page_view` on each internal navigation (SPA), skipping
* the first one (already emitted by the inline script) and the excluded routes.
* Coupled with `send_page_view: false` in the config, this is what prevents
* GA4's enhanced measurement from counting /admin routes
* reached through internal navigation.
*/
function PageViewTracker() {
const pathname = usePathname();
const firstRun = useRef(true);
useEffect(() => {
if (firstRun.current) {
firstRun.current = false;
return; // initial page_view already sent by the inline script
}
if (isExcludedPath(pathname)) return;
window.gtag?.("event", "page_view", {
page_path: pathname,
page_location: window.location.href,
page_title: document.title,
});
}, [pathname]);
return null;
}
export function GoogleAnalytics() {
const [consent, setConsent] = useState(false);
const pathname = usePathname();
const gaId = process.env.NEXT_PUBLIC_GA_MEASUREMENT_ID;
useEffect(() => {
setConsent(localStorage.getItem("cookie-consent") === "accepted");
const handler = () =>
setConsent(localStorage.getItem("cookie-consent") === "accepted");
window.addEventListener("cookie-consent-change", handler);
return () => window.removeEventListener("cookie-consent-change", handler);
}, []);
// No consent, no ID, or excluded route (admin/authenticated area):
// we do not even load gtag.js -> no session_start nor GA cookie dropped,
// so no pollution of the acquisition stats by admin/client sessions.
if (!consent || !gaId || isExcludedPath(pathname)) return null;
return (
<>
<Script
src={`https://www.googletagmanager.com/gtag/js?id=${gaId}`}
strategy="afterInteractive"
/>
<Script id="google-analytics" strategy="afterInteractive">
{`
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '${gaId}', { send_page_view: false });
gtag('event', 'page_view');
`}
</Script>
<PageViewTracker />
</>
);
}Important: This component listens for cookie-consent-change events, so GA loads instantly when the user accepts - no page reload needed.
Exclusion of admin / authenticated routes. The component does not trigger GA4 on any route listed in EXCLUDED_PREFIXES (default: ["/admin"]):
- Direct load of an excluded route (the admin opens
/admin, refreshes, etc.):isExcludedPath(pathname)is true -> the component returnsnull->gtag.jsis never loaded -> nosession_start, no_gacookie, no pollution of the acquisition stats. - Internal navigation to an excluded route (a visitor moves from a public page to
/admin): the config runs withsend_page_view: false(enhanced measurement no longer auto-emits apage_viewon history changes), andPageViewTrackerskips the excluded paths -> the/adminpage is never counted. - The initial
page_viewis emitted by the inline script (reliable, no race withgtag.js);PageViewTrackeronly handles subsequent navigations.
To do after creating the component - offer to broaden the exclusion. Spot the project's authenticated areas and offer the user to add them to EXCLUDED_PREFIXES:
- Detect the candidate route segments (in bash, adapt
<web-root>):
(and the variants underls -d <web-root>/src/app/admin <web-root>/src/app/\(admin\) \ <web-root>/src/app/dashboard <web-root>/src/app/espace-membres \ <web-root>/src/app/compte <web-root>/src/app/account 2>/dev/null<web-root>/src/app/[locale]/…if the project is i18n). - For each authenticated area found (dashboard, members area, account…), offer in plain language to add it to
EXCLUDED_PREFIXESso that logged-in client sessions do not pollute the acquisition stats either. Only add the prefixes the user confirms.- ⚠️ With i18n routes prefixed by the locale (
/fr/compte,/en/account), a bare prefix like/comptewill not match. In that case, add the segment without the locale via a looser comparison, or explicitly list the localized prefixes.
- ⚠️ With i18n routes prefixed by the locale (
Advanced option - exclude every authenticated session (not just by URL). If the project wants to exclude any page as soon as the user is logged in (and not just fixed URL prefixes), and it uses NextAuth with a SessionProvider mounted at the root, you can add a session guard in the component:
import { useSession } from "next-auth/react";
// …
const { status } = useSession();
// in the render, in addition to the other guards:
if (status === "authenticated") return null;Only offer this option if a SessionProvider already wraps the app (otherwise useSession crashes). By default, URL-prefix exclusion is enough and stays simpler.
Step 5 - Create CookieConsent banner
Create a CookieConsent component alongside the GoogleAnalytics component, at src/components/CookieConsent.tsx.
Pattern used: shared i18n-aware templates (preferred over inline code). Hypervibe ships two ready-to-use variants under templates/cookie-banner/:
plain.tsx: single-language version (hardcoded FR text)i18n.tsx: multilingual version (usesuseTranslations("cookies")+Linkfrom~/i18n/routing)
And two message files: messages-fr.json, messages-en.json (key cookies.*).
Procedure
- Detect the project's i18n state: run in bash
if [ -f "<web-root>/src/i18n/routing.ts" ]; then echo i18n; else echo plain; fi - Copy the right template:
- plain: copy
${CLAUDE_SKILL_DIR}/../../templates/cookie-banner/plain.tsxto<web-root>/src/components/CookieConsent.tsx - i18n: copy
${CLAUDE_SKILL_DIR}/../../templates/cookie-banner/i18n.tsxto<web-root>/src/components/CookieConsent.tsx, then run:
to merge thenode "${CLAUDE_SKILL_DIR}/../../scripts/_i18n-merge-messages.mjs" --web-dir <web-root> --feature cookie-bannercookies.*keys into all the project'smessages/<locale>.jsonfiles (with EN fallback for the locales we do not ship).
- plain: copy
- Adjust the colors: both templates have a
bg-black/90background and an "Accept" buttonbg-white text-black. Replace with the project's colors:- Look in
globals.cssor the project'sCLAUDE.mdfor the main accent color - Replace
bg-white(on the accept button) with the accent class. Dark text on a light accent, white on a dark accent.
- Look in
Important: NEVER mention a specific tool in the message (no "Google Analytics", "Meta Pixel", etc.) - the generic wording must stay valid even if the user adds other tracking tools later. This is already the case by default in the templates ("audience measurement").
Component detail (for reference - do not rewrite by hand, copy the template)
Design rules:
- Small popup in the bottom-left corner (not a full-width bar)
- Max width
max-w-sm, roundedrounded-xl, with backdrop blur - Text in
text-xs, discreet and light - Link to privacy policy page using
Link(next/link in single-language, next-intl~/i18n/routingin multilingual) - Two buttons: refuse (outline/ghost) and accept (filled with project accent color)
- Both buttons must have
cursor-pointerclass - Background: semi-transparent dark matching the site's dark color
Why dispatch also on refuse(): if a previous session accepted and loaded GA, then the user refuses, the dispatched event lets GoogleAnalytics (or any future tracker) react (stop sending events, clean the dataLayer). Refusing without a dispatch would leave the previously loaded tracker in zombie mode until the next reload.
openCookiePreferences() helper: exposed for the footer / settings page, it lets you reopen the banner. The CNIL requires that withdrawing consent be as easy as giving it, so a "Manage cookies" link in the footer is the minimum.
Adapt the link to the privacy policy: by default the template points to /politique-de-confidentialite (the path created by /bootstrap). In i18n mode, the Link from ~/i18n/routing automatically prefixes the locale. If the project uses a different path (e.g. /privacy), adjust the href.
Step 6 - Add to root layout
Add both components to the root layout, before </body>:
import { GoogleAnalytics } from "~/components/GoogleAnalytics";
import { CookieConsent } from "~/components/CookieConsent";
// Before </body>:
<GoogleAnalytics />
<CookieConsent />Step 6.5 - Add "Manage cookies" link to the footer (RGPD requirement)
This is legally required. The CNIL mandates that the user must be able to withdraw consent at any time, with the same level of effort as giving it. A discreet link in the footer fulfills this obligation.
Locate the project's footer component (typically src/components/layout/footer.tsx, src/components/Footer.tsx, or similar). Add a button alongside the other legal links (e.g. next to "Mentions légales", "Politique de confidentialité"):
import { openCookiePreferences } from "~/components/shared/CookieConsent";
// (or wherever CookieConsent lives in this project)
// In the footer legal links row:
<button
type="button"
onClick={openCookiePreferences}
className="cursor-pointer text-xs text-muted-foreground transition-colors hover:text-primary"
>
{/* If the project has i18n: */}
{t("manageCookies")}
{/* Else: */}
Gérer mes cookies
</button>If the project has i18n : add the translation key to all message files:
- FR:
"manageCookies": "Gérer mes cookies" - EN:
"manageCookies": "Manage cookies" - JA:
"manageCookies": "Cookieを管理" - ES:
"manageCookies": "Gestionar cookies" - DE:
"manageCookies": "Cookies verwalten"
Place it in the same namespace as the other footer legal links (typically footer.manageCookies).
Note : if the project has no footer yet (rare), skip this step but inform the user - they'll need to add the link manually when they build their footer.
Step 7 - Update legal pages (RGPD)
This is mandatory for RGPD compliance.
Add Google Analytics to the project's RGPD subprocessor registry:
node "${CLAUDE_SKILL_DIR}/../../scripts/update-privacy-policy.mjs" --add google-analyticsThe helper is idempotent. The google-analytics key automatically marks the subprocessor as requiring consent (requiresConsent: true). If the politique-de-confidentialite/page.tsx page exists (created by /bootstrap), it updates automatically from the registry.
If the project has a hand-written privacy policy (not generated by bootstrap), open it and:
- Replace any "no cookies" / "aucun cookie" mention with the new reality
- Mention that the site uses audience measurement cookies (Google Analytics) dropped only after explicit consent
- Mention that the user can withdraw their consent at any time by clearing the browser cookies
- Add Google to the list of subprocessors if not already present
If the site has i18n, update ALL language files.
Step 8 - Update CLAUDE.md
Invoke _update-claude-md with:
stack:- **Analytics**: Google Analytics (GA4) with RGPD cookie consentenv-vars:- \NEXT_PUBLIC_GA_MEASUREMENT_ID` - GA4 Measurement ID`conventions:- Tracking with consent: to add a tool that drops cookies (Meta Pixel, Hotjar, LinkedIn Insight Tag, etc.), reuse the pattern of \GoogleAnalytics.tsx` - read `localStorage.cookie-consent === "accepted"` + listen to the `cookie-consent-change` event to load the script conditionally. Do NOT change the banner wording to mention the new tool: the "audience measurement" text covers any tracker by default.`- Analytics exclusion: \GoogleAnalytics.tsx` does not trigger GA4 on any route listed in `EXCLUDED_PREFIXES` (default `["/admin"]`) - gtag.js is not loaded on these routes (no pollution of the acquisition stats by admin/client sessions) and internal navigations to these routes are not counted (`send_page_view: false` + `PageViewTracker`). To also exclude an authenticated area, add its URL prefix to `EXCLUDED_PREFIXES`.`
Step 9 - Proposal: regular email report (optional)
Once analytics is configured and CLAUDE.md is updated, offer the user to enable GA4's scheduled email reports. This is useful to keep an eye on their traffic without having to open Google Analytics every week.
⚠️ Technical note: this feature is 100% UI in Google Analytics. No Google API lets you configure it programmatically. Your added value here is the click-by-click guidance - NEVER claim to have enabled the scheduling yourself.
9.a - Intro question
Do you want to receive a regular email report with your statistics (number of visitors, most viewed pages, where visitors come from, etc.) - without having to open Google Analytics?
Google Analytics offers this feature natively, it takes 2 minutes to enable in their interface. I guide you step by step if you want.
Use AskUserQuestion with two options:
- Yes, guide me -> continue to 9.b
- Not now (I will do it later or not at all) -> skip to Step 10, and mention in the summary that the user can enable this later via the GA4 docs.
9.b - Step-by-step guidance
Show this procedure as-is (the audience is often new to this, every step counts):
Set up a scheduled email report in Google Analytics:
- Go to https://analytics.google.com/ and select your property via the drop-down list at the top of the page (if you have several, it is the one we just configured).
- In the left menu, click Reports.
- Choose the report you want to receive. To get started, I recommend "Pages and screens" (Engagement section): it gives you the ranking of your most viewed pages - it is the most useful day-to-day metric.
- At the top right of the report, click the Share icon (three small dots connected to each other by lines, like a mini graph).
- Choose "Schedule email".
- Configure:
- Recipients: your email (add other people if you want - partners, collaborators…)
- Frequency: weekly (every Monday for example) for tight monitoring, or monthly if you are starting out and traffic is still light
- Format: PDF (readable directly in your email) or CSV (if you want to reuse the data in a spreadsheet)
- Subject and message: customize them, or leave the default values
- Click Save.
You can repeat for other useful reports:
- Acquisition > Overview: where your visitors come from (Google, social media, direct access…)
- Engagement > Events: the interactions on your site (clicks, form submissions if you have configured custom events)
- Demographics > Overview: countries, languages, devices used
Scheduled reports can be edited or deleted from Admin > Scheduled reports (at the bottom of the left menu).
9.c - Wait for confirmation
Tell me when it is done - or if you prefer to handle it later, no worries, we can continue.
If the user says "it is done" -> add to the summary the line "📬 GA4 scheduled email report enabled" + continue to Step 10.
If the user says "later" -> mention in the summary that the guidance is available by re-running /add-analytics (re-configuration mode).
Step 10 - Summary
Tell the user:
- Google Analytics is installed with RGPD consent
- Tracking only triggers after the cookies are accepted
- The admin routes (
/admin) are excluded from tracking: no admin session is counted as discovery traffic. If authenticated areas (dashboard, members area, account) were added to the exclusion, remind them here. Specify that the list is set inEXCLUDED_PREFIXESat the top ofGoogleAnalytics.tsx. - Discreet cookie banner in the bottom left with the project's accent color
- Legal pages updated
- Data visible on https://analytics.google.com/
- To track custom events:
window.gtag?.("event", "event_name", { param: "value" }) - If scheduled email reports were configured in Step 9: remind that the user can manage their reports in GA4 -> Admin -> Scheduled reports
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

