agentleFS
datnpqdatnpq/gskill/skills/conversion-tracking/SKILL.md

conversion-tracking

Skill0 starsChanged 48 days agoMITView on GitHub

Set up GA4 + Google Ads conversion measurement that bidding can actually learn from — gtag loader, privacy-safe page_location/page_title, server-sourced purchase and sign_up events with transaction_id and value, GA4 key events, importing GA4 conversions into Ads, URL-based page-load conversions. Use when adding analytics/ads tracking to a site, when Ads shows "no conversions", or when auditing a tag for PII leaks.

3 other projects use a version of this.

Adopted by

Most recently taken up by

The file

We split this skill into the rules it gives an agent

6 rules. About 0 are common, 2 are distinctive, and 4 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈2

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 4

    Very specific

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

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Don't scrape values from the DOM ("Amount: 160.000đ" → regex in GTM).

    line 47
  2. Very specific:

    Only for genuinely new events: a returning user signing in is not a sign_up.

    line 65
  3. Very specific:

    Check "Pages and screens" and "Session source/medium" for leaks (names in titles, internal test traffic such as localhost:xxxx / referral).

    line 78
  4. Distinctive:

    Import → Google Analytics 4).

    line 84
  5. Very specific:

    Verify the AW- id on the site belongs to *this* Ads account (Data manager / Google tag).

    line 91
  6. Very specific:

    Run ${CLAUDE_PLUGIN_ROOT}/scripts/audit_site.py https://example.com for the static checks, then in a real browser open …

    line 96

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

Conversion tracking (GA4 + Google Ads)

Goal: every conversion that matters reaches GA4 once, with the real amount and a stable transaction id, attributed to the ad click that caused it, and nothing personal leaves the page. Then Ads imports it and bids on it.

1. One loader, two destinations

Load gtag once (with the GA4 id if there is one) and config each destination. Template: ${CLAUDE_PLUGIN_ROOT}/templates/gtag-snippet.html. The parts that are easy to get wrong:

gtag('set', 'url_passthrough', true);          // keep gclid across internal links (no cookies needed)

// Keep ONLY ad-attribution params. Stripping the whole query string (a common
// "privacy" fix) also strips gclid → GA4 cannot tie the session to the ad click →
// the purchase imported into Ads is not credited to the campaign. Silent failure.
var keep = /^(gclid|gbraid|wbraid|dclid|utm_(source|medium|campaign|term|content|id))$/;
var q = new URLSearchParams();
new URLSearchParams(location.search).forEach(function (v, k) { if (keep.test(k)) q.set(k, v); });
var pageLocation = location.origin + location.pathname + (q.toString() ? '?' + q : '');
var pageReferrer = '';
try { var u = new URL(document.referrer); pageReferrer = u.origin + u.pathname; } catch (e) {}

gtag('config', 'G-XXXXXXX',   { page_location: pageLocation, page_referrer: pageReferrer, page_title: SAFE_TITLE });
gtag('config', 'AW-XXXXXXXXX',{ page_location: pageLocation, page_referrer: pageReferrer, page_title: SAFE_TITLE });

page_title leaks PII by default. GA4 records document.title. Titles like "Account of John Smith" or "Reading for <name>" put real names into Analytics, which Google's policy forbids (property can be purged/suspended). Rule that scales: pages that are noindex (private) send a generic title — strip everything after " of " / " — ". Do it server-side so the name never appears in the gtag block at all, and add a test that renders a private page with a known fake name and asserts the name is absent from the gtag script.

allow_google_signals: false and allow_ad_personalization_signals: false are fine for conversion counting; they do prevent building remarketing audiences. Make it a conscious choice and tell the user.

2. Conversion events come from the server

Don't scrape values from the DOM ("Amount: 160.000đ" → regex in GTM). It breaks the day someone edits the page copy, and it can be spoofed. Emit the event from the backend at the moment the order is confirmed paid:

gtag('event', 'purchase', {
  transaction_id: 'order-<id>',   // GA4 and Ads both de-duplicate on this: reloads count once
  value: 160000, currency: 'VND',
  items: [{ item_id: 'sku', item_name: 'name', price: 160000, quantity: 1 }]
});
gtag('event', 'sign_up', { method: 'google' });  // new accounts only

Delivery pattern:

  • The event happens in a request that renders a page (payment return page): print it on that page ("flash now").
  • The event happens in a JSON/XHR request followed by a JS redirect (OAuth sign-in): store it in the session and print it on the next page ("flash"). Otherwise it is lost.
  • Only for genuinely new events: a returning user signing in is not a sign_up.

Optionally also fire an Ads-native conversion (send_to: 'AW-…/label') with the same transaction_id, but if GA4 is imported into Ads, one source is enough — two primary actions for the same thing double-count.

3. GA4 settings

  • Admin → Events → mark purchase as a key event (star). sign_up can only be starred after the first one arrives — GA4 lists recent events only. Put it on the follow-up list.
  • Admin → Product links → Google Ads links: link the Ads account (Personalized advertising on if they want audiences).
  • Admin → Product links → Search Console links: link the Domain property to the web stream.
  • Check "Pages and screens" and "Session source/medium" for leaks (names in titles, internal test traffic such as localhost:xxxx / referral).

4. Google Ads conversion actions

  • Primary, drives bidding: the GA4-imported purchase (Goals → Conversions → New → Import → Google Analytics 4). Value: use the value from the event.
  • Secondary or softer primary: a page load conversion on a deep-funnel URL (e.g. "URL starts with example.com/result") — cheap signal that needs no code, uses the account's Google tag. Choose a page only real users reach.
  • Newly created actions sit in "Pending / Lượt chuyển đổi đang chờ" for up to 48 h. That is normal. "Needs attention / Cần chú ý" on a goal right after creation is also normal. Re-check after 48 h; if still pending, the tag on the site is not this account's.
  • Verify the AW- id on the site belongs to this Ads account (Data manager / Google tag). A tag from another account compiles, loads, and records nothing here.

5. Verify (don't trust, check)

Run ${CLAUDE_PLUGIN_ROOT}/scripts/audit_site.py https://example.com for the static checks, then in a real browser open https://example.com/?gclid=TEST&utm_source=google&secret=x and run ${CLAUDE_PLUGIN_ROOT}/scripts/check_gtag.js in the console. Expect: one config per destination, gclid and utm_source kept, secret dropped, no personal title. Finally make a real (or sandbox) purchase and watch GA4 Realtime.

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.