Tips & Tricks (Actualizado: 3/6/2026)

Implementar Analytics con Claude Code: GA4, GSC, Cloudflare y Revenue

Implementa analytics con Claude Code: GA4, GSC, Cloudflare, PV, CTA, ingresos y pruebas.

Implementar Analytics con Claude Code: GA4, GSC, Cloudflare y Revenue

Analytics empieza antes de instalar la etiqueta

Implementar analytics significa convertir PV, clics, lectura completa, consultas, clics a productos y compras en datos útiles para decidir. PV es page view, una vista de página. Un evento es una acción registrada. Una conversión o key event en GA4 es una acción que el negocio considera resultado. UTM son etiquetas de campaña en la URL. Consentimiento es la regla que decide si el navegador puede enviar medición.

Claude Code ayuda porque puede transformar el plan de medición en código, pruebas y documentación. En la operación del sitio de Masa, el error fue mirar crecimiento de PV sin separar clics a producto, formularios completados y registros a recursos gratuitos. El tráfico parecía sano, pero el camino hacia ingresos era invisible.

La pila práctica de este artículo es: GA4 para campañas y eventos clave, Search Console para demanda por query y página, Cloudflare para señales de borde, Plausible para objetivos ligeros y PostHog para funnels. Puedes conectarlo con optimización SEO, A/B testing, performance y auditoría del funnel.

Plan de medición

Pide a Claude Code una tabla desde decisiones, no desde herramientas.

Crea un plan de implementación analytics para este sitio de contenido.
El objetivo no es solo crecer en PV, sino mejorar lectura completa, clics CTA, consultas, clics a producto y compras.
Usa columnas business_question, event_name, trigger, required_params, provider, decision.
Usa eventos recomendados de GA4 cuando encajen. Los propios van en snake_case.
business_questionevent_nametriggerrequired_paramsproviderdecision
¿Se lee el artículo hasta el final?article_read_completeFooter visible al 70%slug, category, reading_time_secGA4/PostHogReescribir intro, headings e internos
¿Se hace clic en CTA?cta_clickCTA de producto, formación o PDFslug, cta_id, cta_type, target_urlGA4/Plausible/PostHogCambiar posición y copy
¿La consulta se completa?generate_leadFormulario enviado con éxitoform_id, lead_source, value, currencyGA4/PostHogMejorar formulario y oferta
¿El producto genera intención?purchase_link_clickClic a producto o Gumroadproduct_id, price, currency, slugGA4/PostHogAjustar artículo y producto
¿Qué queries valen la pena?gsc_query_pageSearch Console API devuelve page/querypage, query, clicks, impressions, ctr, positionGSCPriorizar títulos y actualizaciones
¿Faltan tags de navegador?edge_page_viewCloudflare Worker recibe requestpath, country, status, duration_msCloudflareDetectar bloqueos y problemas de velocidad

Los eventos de GA4 deben revisarse en recommended events. Usa generate_lead cuando el significado coincida; deja eventos propios para acciones específicas del artículo.

flowchart LR
  Reader["Lector"]
  Consent["Consentimiento"]
  Browser["browser analytics.js"]
  Server["GA4 Measurement Protocol"]
  GSC["Search Console API"]
  Edge["Cloudflare Worker"]
  Dashboard["Dashboards de contenido, ingresos y calidad"]

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

Contrato de eventos en JS

El contrato evita que Claude Code cree ctaClick, cta_click y button_click para la misma acción.

// 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/" }));
}

Separa products de training. El primero mide interés por plantillas o guías; el segundo mide intención de adopción en equipo o consultoría.

Capa del navegador

Esta capa concentra consentimiento, UTM, limpieza de parámetros y envío a GA4, Plausible y PostHog.

// 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);
}

Envía generate_lead después del éxito del formulario, no en el clic del botón. Para lectura completa usa un único disparo cuando el final del artículo aparece.

GA4, GSC y Cloudflare

Los resultados confirmados en servidor pueden enviarse con GA4 Measurement Protocol y validarse con 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 se consulta con 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));
}

Para señales de borde, usa Workers Analytics Engine y el ejemplo de 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 });
  },
};

No guardes email, nombre, texto libre ni IP cruda en Cloudflare. Guarda slug, evento, país, estado y tiempo.

Casos de uso y errores

Caso 1: SEO. Si GSC muestra muchas impresiones y poco CTR, revisa título y description. Si PV es alto pero article_read_complete bajo, cambia intro y estructura. Caso 2: productos. Con purchase_link_click puedes saber qué artículos llevan a producto y qué precio interesa. Caso 3: formación. cta_click mide interés; generate_lead mide formulario completado. Caso 4: campañas. Guarda UTM al aterrizar para no perder la fuente cuando la consulta llega después.

Errores concretos: nombres de evento inconsistentes, envío antes de consentimiento, conversiones duplicadas por cliente y servidor, tratar GSC como log completo, y cargar tantos scripts que empeoran Core Web Vitals. Divide dashboards en crecimiento editorial, funnel de ingresos y calidad técnica. Revisa GA4 DebugView, Realtime, Plausible Goals, PostHog Events y Cloudflare dentro de 24 horas.

Para ordenar una instalación real, usa products si necesitas plantillas o training si el equipo necesita revisar medición, implementación y dashboards juntos.

#Claude Code #analytics #GA4 #Plausible #PostHog
Gratis

PDF gratis: cheatsheet de Claude Code

Introduce tu email y descarga una hoja con comandos, hábitos de revisión y flujos seguros.

Cuidamos tus datos y no enviamos spam.

Masa

Sobre el autor

Masa

Ingeniero enfocado en workflows prácticos con Claude Code.