Tips & Tricks (Mis à jour: 03/06/2026)

Implémenter l'analytics Claude Code : GA4, GSC, Cloudflare et revenus

Implémentez l'analytics Claude Code avec GA4, GSC, Cloudflare, PV, CTA, revenus et tests.

Implémenter l'analytics Claude Code : GA4, GSC, Cloudflare et revenus

L’analytics commence avant la balise

Implémenter l’analytics consiste à transformer PV, clics, lecture complète, demandes, clics produits et achats en données utiles. Une PV est une page vue. Un événement est une action enregistrée. Une conversion, ou key event GA4, est une action qui compte pour le business. Les UTM sont des marqueurs de campagne dans l’URL. Le consentement décide si le navigateur peut envoyer des données.

Claude Code est utile car il convertit un plan de mesure en code, tests et documentation. Dans l’exploitation du site de Masa, l’erreur a été de suivre la croissance des PV sans distinguer clics produit, formulaires terminés et inscriptions aux ressources gratuites. Le trafic semblait bon, mais le chemin vers le revenu restait invisible.

La pile utilisée ici est simple : GA4 pour campagnes et événements clés, Search Console pour requêtes et pages, Cloudflare pour signaux edge, Plausible pour objectifs légers, PostHog pour funnels. À lire aussi : SEO, A/B testing, performance et audit du funnel.

Plan de mesure

Demandez d’abord à Claude Code une table partant des décisions.

Prépare un plan analytics pour ce site de contenu.
L'objectif n'est pas seulement la croissance des PV, mais lecture complète, clics CTA, demandes, clics produit et achats.
Utilise business_question, event_name, trigger, required_params, provider, decision.
Utilise les événements recommandés GA4 quand ils conviennent. Les événements propres sont en snake_case.
business_questionevent_nametriggerrequired_paramsproviderdecision
L’article est-il lu ?article_read_completeFooter visible à 70%slug, category, reading_time_secGA4/PostHogRéécrire intro, titres, liens
Les CTA sont-ils cliqués ?cta_clickCTA produit, formation ou PDFslug, cta_id, cta_type, target_urlGA4/Plausible/PostHogChanger position et texte
La demande est-elle terminée ?generate_leadFormulaire envoyé avec succèsform_id, lead_source, value, currencyGA4/PostHogAméliorer formulaire et offre
Les produits créent-ils une intention ?purchase_link_clickClic produit ou Gumroadproduct_id, price, currency, slugGA4/PostHogAligner article et produit
Quelles requêtes valent l’effort ?gsc_query_pageSearch Console API retourne page/querypage, query, clicks, impressions, ctr, positionGSCChoisir titres et mises à jour
Les tags navigateur manquent-ils du trafic ?edge_page_viewCloudflare Worker reçoit une requêtepath, country, status, duration_msCloudflareDétecter blocage et lenteur

Vérifiez les événements GA4 dans recommended events. Utilisez generate_lead quand le sens correspond et gardez les événements propres pour les actions éditoriales.

flowchart LR
  Reader["Lecteur"]
  Consent["Consentement"]
  Browser["browser analytics.js"]
  Server["GA4 Measurement Protocol"]
  GSC["Search Console API"]
  Edge["Cloudflare Worker"]
  Dashboard["Contenu, revenus, qualité"]

  Reader --> Consent --> Browser
  Browser --> Server
  GSC --> Dashboard
  Edge --> Dashboard
  Browser --> Dashboard
  Server --> Dashboard

Contrat d’événements

Le contrat évite les variantes de nom et force les paramètres nécessaires.

// event-plan.mjs
import { pathToFileURL } from "node:url";

export const eventPlan = {
  article_read_complete: { required: ["slug", "category", "reading_time_sec"], providers: ["GA4", "PostHog"] },
  cta_click: { required: ["slug", "cta_id", "cta_type", "target_url"], providers: ["GA4", "Plausible", "PostHog"] },
  generate_lead: { required: ["form_id", "lead_source", "value", "currency"], providers: ["GA4", "PostHog"] },
  purchase_link_click: { required: ["product_id", "price", "currency", "slug"], providers: ["GA4", "PostHog"] },
  campaign_landing: { required: ["utm_source", "utm_medium", "utm_campaign"], providers: ["GA4"] },
};

export function validateEvent(name, params = {}) {
  const contract = eventPlan[name];
  if (!contract) return { ok: false, missing: ["known_event_name"] };
  const missing = contract.required.filter((key) => params[key] === undefined || params[key] === "");
  return { ok: missing.length === 0, missing };
}

if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
  console.log(validateEvent("cta_click", { slug: "claude-code-analytics-implementation", cta_id: "products_footer", cta_type: "product", target_url: "/en/products/" }));
}

Séparez products et training. Le premier signale un intérêt pour des guides ou templates ; le second signale un besoin d’accompagnement d’équipe.

Couche navigateur

La couche navigateur gère consentement, UTM, nettoyage des paramètres et envoi aux fournisseurs.

// browser-analytics.js
const CONSENT_KEY = "analytics_consent";
const UTM_KEYS = ["utm_source", "utm_medium", "utm_campaign", "utm_term", "utm_content"];

function inBrowser() {
  return typeof window !== "undefined" && typeof localStorage !== "undefined";
}

function hasConsent() {
  return inBrowser() && localStorage.getItem(CONSENT_KEY) === "granted";
}

function cleanParams(params = {}) {
  return Object.fromEntries(Object.entries(params).filter(([, value]) => value !== undefined && value !== null && value !== "").map(([key, value]) => [key, typeof value === "boolean" ? Number(value) : value]));
}

export function setAnalyticsConsent(state) {
  if (!inBrowser()) return;
  localStorage.setItem(CONSENT_KEY, state);
  window.gtag?.("consent", "update", { analytics_storage: state, ad_storage: "denied" });
}

export function readUtmParams() {
  if (!inBrowser()) return {};
  const current = new URLSearchParams(window.location.search);
  const saved = JSON.parse(localStorage.getItem("landing_utm") || "{}");
  const next = { ...saved };
  for (const key of UTM_KEYS) {
    const value = current.get(key);
    if (value) next[key] = value;
  }
  localStorage.setItem("landing_utm", JSON.stringify(next));
  return next;
}

export function trackEvent(name, params = {}) {
  if (!hasConsent()) return;
  const payload = cleanParams({ ...readUtmParams(), ...params });
  window.gtag?.("event", name, payload);
  window.plausible?.(name, { props: payload });
  window.posthog?.capture(name, payload);
}

Envoyez generate_lead après réussite du formulaire. Pour la lecture complète, envoyez un seul événement lorsque la fin de l’article devient visible.

GA4, GSC et Cloudflare

Les résultats confirmés côté serveur passent par GA4 Measurement Protocol et doivent être testés avec validation server.

// ga4-server-event.mjs
import { pathToFileURL } from "node:url";

const { GA4_MEASUREMENT_ID, GA4_API_SECRET, GA4_DEBUG } = process.env;
if (!GA4_MEASUREMENT_ID || !GA4_API_SECRET) throw new Error("GA4_MEASUREMENT_ID and GA4_API_SECRET are required");

export async function sendGa4Event({ clientId, name, params = {} }) {
  const endpoint = new URL(GA4_DEBUG === "1" ? "https://www.google-analytics.com/debug/mp/collect" : "https://www.google-analytics.com/mp/collect");
  endpoint.searchParams.set("measurement_id", GA4_MEASUREMENT_ID);
  endpoint.searchParams.set("api_secret", GA4_API_SECRET);
  const response = await fetch(endpoint, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ client_id: clientId, events: [{ name, params }] }) });
  if (!response.ok) throw new Error("GA4 request failed with status " + response.status);
  if (GA4_DEBUG === "1") {
    const result = await response.json();
    if (result.validationMessages?.length) throw new Error(JSON.stringify(result.validationMessages, null, 2));
  }
}

if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
  await sendGa4Event({ clientId: "555.1234567890", name: "generate_lead", params: { form_id: "training", lead_source: "article_footer", value: 1, currency: "USD" } });
  console.log("sent");
}

Search Console utilise Search Analytics API.

// gsc-query.mjs
import { pathToFileURL } from "node:url";

const { GSC_ACCESS_TOKEN, GSC_SITE_URL = "https://example.com/" } = process.env;
if (!GSC_ACCESS_TOKEN) throw new Error("GSC_ACCESS_TOKEN is required");

export async function querySearchConsole({ startDate, endDate, pageContains }) {
  const endpoint = "https://www.googleapis.com/webmasters/v3/sites/" + encodeURIComponent(GSC_SITE_URL) + "/searchAnalytics/query";
  const response = await fetch(endpoint, {
    method: "POST",
    headers: { authorization: "Bearer " + GSC_ACCESS_TOKEN, "content-type": "application/json" },
    body: JSON.stringify({ startDate, endDate, dimensions: ["page", "query"], dimensionFilterGroups: pageContains ? [{ filters: [{ dimension: "page", operator: "contains", expression: pageContains }] }] : [], rowLimit: 25 }),
  });
  if (!response.ok) throw new Error("Search Console request failed with status " + response.status);
  return response.json();
}

if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
  const data = await querySearchConsole({ startDate: "2026-05-01", endDate: "2026-05-31", pageContains: "/blog/claude-code-analytics-implementation" });
  console.log(JSON.stringify(data.rows ?? [], null, 2));
}

Pour les signaux edge, consultez Workers Analytics Engine et l’exemple writeDataPoint.

// cloudflare-worker.js
function json(data, status = 200) {
  return new Response(JSON.stringify(data), { status, headers: { "content-type": "application/json" } });
}

export default {
  async fetch(request, env) {
    if (request.method !== "POST") return json({ ok: false, error: "method_not_allowed" }, 405);
    const event = await request.json().catch(() => null);
    if (!event?.event_name || !event?.slug) return json({ ok: false, error: "event_name_and_slug_required" }, 400);
    const country = request.cf?.country || request.headers.get("cf-ipcountry") || "XX";
    env.ANALYTICS?.writeDataPoint({ blobs: [event.event_name, event.slug, event.cta_id || "", country], doubles: [Number(event.value || 1)], indexes: [String(event.slug).slice(0, 96)] });
    return json({ ok: true });
  },
};

Ne stockez pas email, nom, texte libre ou IP brute dans Cloudflare.

Cas d’usage et pièges

Cas 1 : SEO. Beaucoup d’impressions GSC et peu de CTR indiquent un problème de titre ou description. Beaucoup de PV et peu de lecture complète indiquent un problème d’introduction ou de structure. Cas 2 : produits. purchase_link_click avec product_id, price, currency et slug montre quels articles mènent aux offres. Cas 3 : formation. cta_click mesure l’intérêt, generate_lead mesure la demande réussie. Cas 4 : campagnes. Les UTM doivent survivre jusqu’au formulaire.

Pièges : noms incohérents, envoi avant consentement, doublons client/serveur, GSC traité comme journal complet, trop de scripts tiers et Core Web Vitals dégradés. Séparez les dashboards en contenu, revenus et qualité. Vérifiez GA4 DebugView, Realtime, Plausible Goals, PostHog Events et Cloudflare sous 24 heures.

Pour une configuration existante, products aide avec les templates et training convient si l’équipe veut revoir plan de mesure, code et tableaux de bord ensemble.

#Claude Code #analytics #GA4 #Plausible #PostHog
Gratuit

PDF gratuit: cheatsheet Claude Code

Saisissez votre email et téléchargez une page avec commandes, habitudes de review et workflow sûr.

Nous protégeons vos données et n'envoyons pas de spam.

Masa

À propos de l'auteur

Masa

Ingénieur spécialisé dans les workflows pratiques avec Claude Code.