agentleFS
ZmokiZmoki/zmoki-astro-starter/.claude/skills/analytics/SKILL.md

analytics

Skill4 starsChanged 18 days agoMITView on GitHub

Add, enable, or swap analytics providers, or add a tracked event. Use when the user wants to turn on PostHog or Google Tag Manager, plug in another analytics tool (Plausible, Fathom, GA4, Umami, …), disable analytics, or track a new event.

69 other projects use a version of this.

Adopted by

Most recently taken up by

Used with

Projects with it also use popups, free-tools and 10 more.

Other files people use alongside this one.

Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
  • CesarjoquinSkill

    popups

    When the user wants to create or optimize popups, modals, overlays, slide-ins, or banners for conversion purposes. Also use when the user mentions "exit intent," "popup conversions," "modal optimization," "lead capture popup," "email popup," "announcement banner," "overlay," "collect emails with a popup," "exit popup," "scroll trigger," "sticky bar," or "notification bar." Use this for any overlay or interrupt-style conversion element. For forms outside of popups, see cro. For general page conversion optimization, see cro.

    Also in 23 projects that use this

  • CesarjoquinSkill

    free-tools

    When the user wants to plan, evaluate, or build a free tool for marketing purposes — lead generation, SEO value, or brand awareness. Also use when the user mentions "engineering as marketing," "free tool," "marketing tool," "calculator," "generator," "interactive tool," "lead gen tool," "build a tool for leads," "free resource," "ROI calculator," "grader tool," "audit tool," "should I build a free tool," or "tools for lead gen." Use this whenever someone wants to build something useful and give it away to attract leads or earn links. For downloadable content lead magnets (ebooks, checklists, templates), see lead-magnets.

    Also in 24 projects that use this

  • coreyhaines31Skill

    marketing-council

    When the user wants multiple expert perspectives on a marketing question — a simulated board of advisors staffed by legendary marketers (Seth Godin, David Ogilvy, Eugene Schwartz, April Dunford, Rory Sutherland, Alex Hormozi, Byron Sharp, and more). Also use when the user mentions 'marketing council,' 'board of advisors,' 'advisory board,' 'what would Seth Godin say,' 'what would Ogilvy think,' 'channel Hormozi,' 'get multiple perspectives,' 'debate this,' 'have the council review,' 'marketing mentors,' or asks how a famous marketer would approach their problem. The council gives each advisor's take through their documented frameworks, surfaces where they disagree, and synthesizes a recommendation. For executing the winning direction, hand off to positioning, offers, copywriting, ads, or the relevant skill.

    Also in 19 projects that use this

  • roerohanSkill

    emails

    When the user wants to create or optimize an email sequence, drip campaign, automated email flow, or lifecycle email program. Also use when the user mentions "email sequence," "drip campaign," "nurture sequence," "onboarding emails," "welcome sequence," "re-engagement emails," "email automation," "lifecycle emails," "trigger-based emails," "email funnel," "email workflow," "what emails should I send," "welcome series," or "email cadence." Use this for any multi-email automated flow. For cold outreach emails, see cold-email. For in-app onboarding, see onboarding.

    Also in 21 projects that use this

  • ukunal91appSkill

    community-marketing

    Build and leverage online communities to drive product growth and brand loyalty. Use when the user wants to create a community strategy, grow a Discord or Slack community, manage a forum or subreddit, build brand advocates, increase word-of-mouth, drive community-led growth, engage users post-signup, or turn customers into evangelists. Trigger phrases: "build a community," "community strategy," "Discord community," "Slack community," "community-led growth," "brand advocates," "user community," "forum strategy," "community engagement," "grow our community," "ambassador program," "community flywheel.

    Also in 26 projects that use this

  • coreyhaines31Skill

    marketing-loops

    When the user wants to set up a recurring, self-running marketing workflow — a repeatable loop an AI agent runs on a cadence (weekly, daily, on a trigger) rather than a one-off task. Also use when the user mentions 'marketing loop,' 'recurring marketing workflow,' 'automate my marketing,' 'marketing on autopilot,' 'weekly marketing review,' 'ad fatigue check,' 'weekly ads check,' 'content refresh loop,' 'churn watch,' 'ranking drop alert,' 'run my SEO,' 'SEO operator,' 'daily SEO agent,' 'run my outbound,' 'AI SDR,' 'reply triage,' 'always-on marketing,' 'marketing automation workflow,' or 'run this every week.' Use this to pick, adapt, and schedule an ongoing marketing loop that orchestrates the other marketing skills. For one-off marketing ideas, see marketing-ideas. For the experimentation loop specifically, see ab-testing.

    Also in 10 projects that use this

  • +6 more from Cesarjoquin

The file

We split this skill into the rules it gives an agent

9 rules. 0 are common, 1 is distinctive, and 8 are very specific to this project.

  • 0

    Common

    Most of the 58 edited versions we read keep these.

  • 1

    Distinctive

    This author's own choices. Worth a look.

  • 8

    Very specific

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

  • Common
  • Distinctive
  • Very specific
  • could be automatic: a setting could enforce it
  1. Distinctive:

    Ask the user only if it's unclear:

    line 19
  2. Very specific:

    Config module: create src/components/analytics/<p>-config.ts.

    line 41
  3. Very specific:

    Component: create src/components/analytics/<p>.astro.

    line 53
  4. Very specific:

    Keep scripts top-level. A script inside a { } expression breaks Prettier's Astro parser.

    line 76
  5. Very specific:

    Window globals: if the vendor exposes a new global, add it to the Window interface in src/env.d.ts (like posthog / dataLayer).

    line 99
  6. Very specific:

    CSP: add PLAUSIBLE_CSP to providerSources in src/headers/headers.config.ts (never edit the generated public/_headers).

    line 101
  7. Very specific:

    Use snake_case names. Add the event to src/ANALYTICS.md in the same commit.

    line 116
  8. Very specific:

    Check it with npm run dev: analytics is off there, so the console provider logs each call as [analytics] track ….

    line 118
  9. Very specific:

    When the provider set changes, update src/env.d.ts, AGENTS.md → Swappable providers, and SETUP.md → Analytics, forms and captcha.

    line 151

“Common” is measured: kept by at least 6 in 10 of the 58 edited versions of this file we could read. “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

Analytics

Analytics is provider-agnostic and can run several providers at once. Call sites never name a vendor: they call window.track?.(event, props) and window.identify?.(id, props). Each active provider wraps the previous window.track, so one call reaches every provider. Script and CSP rules: AGENTS.md → Scripts and the CSP.

The pieces:

  • src/components/analytics/<p>-config.ts: the provider's committed constants (public values, not env vars), a <p>Configured flag, and a <P>_CSP record of the hosts it needs per CSP directive.
  • src/components/analytics/<p>.astro: loads the vendor and chains onto window.track from a bundled <script>.
  • src/components/Analytics.astro: the dispatcher. Renders each provider whose flag is set, and only when PUBLIC_ANALYTICS_ENABLED === "true". That switch is off by default; it is set in the host's production env and in CI for pushes to main. With it off, or no provider configured, it renders analytics/console.astro, which logs every call to the browser console.

Built in: PostHog (posthog-config.ts) and Google Tag Manager (gtm-config.ts, empty by default).

Pick the task

Ask the user only if it's unclear:

  • A. Enable a built-in provider → Step 1.
  • B. Add a new provider → Step 2.
  • C. Add a tracked event → Step 3.
  • D. Disable analytics → Step 4.

Step 1 — Enable a built-in provider

Set the committed constant:

  • PostHog: POSTHOG_PROJECT_TOKEN and POSTHOG_HOST in src/components/analytics/posthog-config.ts. Both are required.
  • GTM: GTM_CONTAINER_ID (e.g. GTM-XXXXXXX) in src/components/analytics/gtm-config.ts. Set up the actual tags (GA4, Ads, …) in the GTM UI, using a Custom Event trigger on the event name.

Both can be on at once. Then run npm run build:headers and commit public/_headers. Each provider adds its hosts to the CSP only while it's configured, and a changed GTM_CONTAINER_ID also changes the hash of GTM's inline loader. CI's check:headers fails if you skip this.

Analytics still stays off until PUBLIC_ANALYTICS_ENABLED=true. To test locally, prefix the dev or build command with it.

Step 2 — Add a new provider

Let <p> be the provider slug (e.g. plausible).

  1. Config module: create src/components/analytics/<p>-config.ts. headers.config.ts runs under plain node and imports it, so use relative .ts imports only, no @/ alias.

    export const PLAUSIBLE_DOMAIN = "";
    
    export const plausibleConfigured = !!PLAUSIBLE_DOMAIN;
    
    export const PLAUSIBLE_CSP: Record<string, string[]> = plausibleConfigured
      ? { "script-src": ["https://plausible.io"], "connect-src": ["https://plausible.io"] }
      : {};
  2. Component: create src/components/analytics/<p>.astro. Load the vendor, then chain onto window.track from a bundled <script>:

    ---
    import { PLAUSIBLE_DOMAIN } from "@/components/analytics/plausible-config";
    ---
    
    <script
      is:inline
      defer
      data-domain={PLAUSIBLE_DOMAIN}
      src="https://plausible.io/js/script.manual.js"
    ></script>
    <script>
      window.track = ((prev) => (event: string, props?: Record<string, unknown>) => {
        prev?.(event, props);
        window.plausible?.(event, { props });
      })(window.track);
    </script>
    • The external loader may keep is:inline (it's a file on an allowlisted host). The facade must be a bundled script: no raw inline script, no define:vars. If it needs config, import it from the config module.
    • Calling prev is what lets providers coexist. Don't drop it.
    • Keep scripts top-level. A script inside a { } expression breaks Prettier's Astro parser.
    • A pasted vendor snippet can start with /* eslint-disable */ and // @ts-nocheck (see posthog.astro).

    Facade mappings (props are best-effort; some vendors ignore them):

    Providertrack(event, props) →
    GA4 (gtag)gtag('event', event, props)
    Plausibleplausible(event, { props })
    Fathomfathom.trackEvent(event) (no props)
    Umamiumami.track(event, props)
  3. Dispatcher: in src/components/Analytics.astro, import the component and flag and render it:

    import Plausible from "@/components/analytics/plausible.astro";
    import { plausibleConfigured } from "@/components/analytics/plausible-config";
    {analyticsEnabled && plausibleConfigured && <Plausible />}
  4. Window globals: if the vendor exposes a new global, add it to the Window interface in src/env.d.ts (like posthog / dataLayer).
  5. CSP: add PLAUSIBLE_CSP to providerSources in src/headers/headers.config.ts (never edit the generated public/_headers). Run npm run build:headers and commit the artifact. A directive missing from baseDirectives fails the build; add it there first.

Step 3 — Add a tracked event

Fire it from a bundled <script> through the facade. Never name a vendor:

window.track?.("event_name", { some_prop: value, location: bandOf(el) });
  • A click anywhere on the site (a kind of link or button, not one page's element): add it to the delegated listener in src/lib/site-events.ts. For a new standing ask, add its link to site.asks in src/site.config.ts; cta_clicked picks it up.
  • A click or load on one page: a bundled <script> beside the markup, like post_viewed in src/layouts/PostLayout.astro.
  • "Seen" events: trackWhenVisible(el, event, props) from src/lib/analytics.ts fires once when half of el is on screen, like resource_gate_viewed.
  • Location: click events carry location: bandOf(el), the closest data-band. Give a new page section a data-band name.

Use snake_case names. Add the event to src/ANALYTICS.md in the same commit; it's the list of every event the site fires. To tie the visitor to an id (e.g. after a form submit), call window.identify?.(id).

Check it with npm run dev: analytics is off there, so the console provider logs each call as [analytics] track ….

Step 4 — Disable analytics

  • Dev, PRs, previews: already off; the console provider logs events instead. Nothing to do.
  • Production: unset PUBLIC_ANALYTICS_ENABLED in the host's env config.
  • One provider: blank its constant(s) (GTM_CONTAINER_ID = "", or both PostHog constants). It then emits nothing. Run npm run build:headers so its hosts leave the CSP, and commit the artifact.

Step 5 — Verify

npm run format
npm run check
npm run lint
npm run build

A plain build has analytics off. Force it on and check the output:

PUBLIC_ANALYTICS_ENABLED=true npm run build >/dev/null 2>&1
grep -l "posthog.init\|gtm.js?id=" dist/index.html dist/_astro/*.js   # each active provider present
grep -c 'type="module" src="/_astro/' dist/index.html                  # scripts load as files

Then check:

  • Default off: a plain npm run build has no posthog script and no gtm.js?id= in dist/index.html, whatever the constants say. Lighthouse relies on this.
  • CSP: the dev server and astro preview don't send it. Serve dist/ with the headers from public/_headers and load a few pages with DevTools open. A Refused to load for a vendor host means its <P>_CSP lacks it; a Refused to execute inline script means a raw is:inline slipped in.
  • Live: /run the dev server with PUBLIC_ANALYTICS_ENABLED=true and confirm the network request and a test event in the vendor dashboard.

Notes

  • When the provider set changes, update src/env.d.ts, AGENTS.md → Swappable providers, and SETUP.md → Analytics, forms and captcha.
  • Providers must chain before any page script calls track. Bundled scripts run in document order, and <Analytics /> is in <head>, so ordering holds. Don't move <Analytics /> below page scripts.
  • GTM's <noscript> iframe is omitted on purpose: it belongs in <body>, and no-JS visitors can't fire our events anyway.

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.