agentleFS
remix-runremix-run/remix-store/.agents/skills/hydrogen-analytics/SKILL.md

hydrogen-analytics

Skill218 starsChanged 8 days agoMITView on GitHub

Guide for adding or reviewing Hydrogen storefront analytics. Use when working with ShopifyScripts analytics, AnalyticsEvent, consent mode, page/product/ collection/search/cart view events, cart update tracking, custom analytics destinations, or framework route-change analytics wiring.

1 other project uses a version of this, 1 of them edited.

Adopted by

Most recently taken up by

The file

We split this skill into the rules it gives an agent

5 rules. About 0 are common, 3 are distinctive, and 2 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈3

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 2

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Read one browser-lazy singleton from the Shopify global created by ShopifyScripts:

    line 28
  2. Very specific:

    Read shop and i18n values on the server and pass them to ShopifyScripts.

    line 50
  3. Distinctive:

    Do not dispatch server-side analytics through this browser bus.

    line 76
  4. Distinctive:

    Keep ShopifyScripts i18n aligned with the resolved market when the storefront uses markets.

    line 77
  5. Distinctive:

    No browser module reads private or server-only env variables.

    line 85

≈ “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.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Storefront Analytics

Hydrogen's analytics bus owns the event API, event normalization, and consent-gated destination replay. ShopifyScripts owns Shopify consent setup and analytics CDN loading. App code owns when to publish route/view events and when to call cart delta tracking.

Framework References

Before wiring route events, check whether this skill has a reference file for the app's framework in references/. If one exists, read it and use that framework's route-change and lifecycle primitives. If there is no matching reference, keep the core singleton below and adapt page-view, product-view, collection-view, search-view, and cart tracking to the app's own route lifecycle.

Prerequisite: analytics depends on the same-origin SFAPI proxy (see hydrogen-request-handlers) so the browser can observe tracking values from Storefront API responses. The proxy establishes the backend session cookies needed for analytics and checkout continuity; treat analytics as incomplete until it is wired. Key consent setup: Shopify Customer Privacy controls destination delivery in production. Register event consumers with addDestination(); live delivery and replay require analytics consent. Do not bypass Customer Privacy consent gating in production.

Core Pattern

Render Shopify runtime scripts once from the app root/document head with the same resolved market used by Storefront API requests. Use ShopifyScripts from your framework binding if it exports one, or getShopifyScriptTags() / renderShopifyScriptTags() from core in other framework heads. Pass the shop object matching the ShopifyScriptsShop type, and i18n matching the ShopifyScriptsI18n type and serialize them into ShopifyScripts. — declare them as constants with type annotations to keep errors located close to the source of writing. The analytics bus is created by default; pass analytics only for optional bus configuration such as customData. customData isn't added to events you publish; destinations read it via getConfig().customData. Do not pass market country or language through analytics consent config.

Read one browser-lazy singleton from the Shopify global created by ShopifyScripts:

import {
  AnalyticsEvent,
  type StorefrontAnalytics,
  trackCartAnalytics,
} from "@shopify/hydrogen";

export { AnalyticsEvent };

let bus: StorefrontAnalytics | null = null;

export function getAnalytics(): StorefrontAnalytics | null {
  if (typeof window === "undefined") return null;
  bus ??= window.Shopify?.analytics ?? null;
  return bus;
}

export { trackCartAnalytics };

Read shop and i18n values on the server and pass them to ShopifyScripts. Do not read env APIs in browser modules.

In the ShopifyScripts analytics config, channel is optional and defaults to "hydrogen". The "hydrogen" channel is the one that requires storefrontId — it is pulled from the ShopifyScripts shop config into analytics payloads. Headless storefronts pass channel: "headless" in the ShopifyScripts analytics config; the analytics payload then omits storefrontId, but shop.storefrontId itself is still required (pass "0" when the app has no storefront ID).

Publish Events

Publish these from route/page boundaries:

  • PAGE_VIEWED on each page transition.
  • PRODUCT_VIEWED when product data is resolved on a product page.
  • COLLECTION_VIEWED when collection data is resolved.
  • SEARCH_VIEWED when a non-empty search term has results metadata.
  • CART_VIEWED when the full cart page or cart drawer is viewed.
  • Wire cart tracking once per cart store lifecycle with trackCartAnalytics(cartStore) — React apps use the useCartAnalytics() hook from @shopify/hydrogen/react and Vue apps use the useCartAnalytics() composable from @shopify/hydrogen/vue; both call it with the provider's cart store and clean up on unmount. The tracker subscribes to the cart store itself, skips pending/revalidating/note updates, publishes cart delta events on confirmed cart changes, and returns an unsubscribe function. Call it from a client-only effect (useEffect / onMounted), never at cart-store creation time — it throws when window.Shopify.analytics is missing (SSR). Do not manually publish cart delta events.

The bus defaults shop from the top-level shop config passed to ShopifyScripts; pass shop in an event payload only when intentionally overriding that configured value. Shopify analytics reads its content language from window.Shopify.locale. It reads the currency of product events from the event price's currencyCode and falls back to window.Shopify.currency.active, which i18n.currency sets. Page, collection, and search views take only the global. When it is unset, Shopify analytics sends them without a currency.

Required product analytics fields include Shopify Product GID, ProductVariant GID when available, title, price, vendor, quantity, and variant title.

Rules

  • Let Shopify Customer Privacy control destination delivery in production.
  • Initialize one single bus per page lifetime through ShopifyScripts.
  • Register event consumers with addDestination() and use the subscribe function provided to its setup callback.
  • For third-party banners, use consent: {mode: "custom-banner", setup} and read Custom consent providers for readiness, synchronization, and framework integration.
  • Render ShopifyScripts before route components publish events.
  • Do not dispatch server-side analytics through this browser bus.
  • Keep ShopifyScripts i18n aligned with the resolved market when the storefront uses markets.

Verify

  • Page view fires on initial load and client navigations.
  • Product, collection, search, and cart view events fire once per relevant route data change.
  • Confirmed cart data changes flow through trackCartAnalytics(cartStore) (React/Vue bindings: useCartAnalytics()).
  • Consent-denied visitors do not deliver destination events.
  • No browser module reads private or server-only env variables.

Download now (ZIP)

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
What did you use it for? e.g. Reviewing pull requests in a Rails app

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.