gtm-build
Skill4 starsChanged 32 days agoMITView on GitHub
Build tracking in Google Tag Manager from a plan, covering data-layer variables, triggers split by audience, GA4 event tags, Ads conversion tags, consent, review, publish and live verification. Use when the user says "build the tracking", "create the triggers/tags", "implement the tracking plan", "add WhatsApp click tracking", "track phone clicks", or after the tracking-plan skill.
In this repository13 other files it gives its agents.
- ads-auditSkill
- campaign-architectSkill
- consent-auditSkill
- demand-gen-launchSkill
- event-auditSkill
- monthly-reportSkill
- performance-insightsSkill
- pre-launch-checkSkill
- search-launchSkill
- setupSkill
- tracking-auditSkill
- tracking-planSkill
- weekly-checkSkill
The file
We split this skill into the rules it gives an agent
12 rules. About 0 are common, 6 are distinctive, and 6 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈6
Distinctive · estimate
This author's own choices. Worth a look.
6
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 28
Call account_profile first.
- Very specific: line 36
Check for a Conversion Linker: a gclidw tag on All Pages (or a Google tag configured with the AW- ID).
- Very specific: line 65
Consent: Add consent: { required: [...] } to the recipes in steps 4–5 per the plan when creating them.
- Very specific: line 74
Delete (gtm_delete) only when the user explicitly asks.
- Distinctive: line 92
No cross-firing between audiences.
- Distinctive: line 94
Delete test leads from the CRM.
- Distinctive: line 106
Never publish without showing the full workspace diff and getting a yes, and never publish unexplained changes someone else left in the …
- Very specific: line 108
Never bypass a "NOT BUILT" pre-flight finding with gtm_upsert.
- Distinctive: line 109
Never trigger on visible text or page views for a lead.
- Distinctive: line 110
Never delete tags, triggers or conversion actions unless the user asks.
- Distinctive: line 111
Never call tracking broken from one headless or ad-blocked test.
- Very specific: line 112
If the profile is read-only (no write tools), deliver the build plan as a list of exact recipes and tell the user that building needs npx …
≈ “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.
Files
GTM build
Turn a tracking plan into a published, verified Tag Manager container, one previewed step at a time, with a rollback
target noted before anything goes live. Every tag, trigger and variable comes from a typed gtm_build recipe, so
creates don't depend on hand-written JSON.
When to use
- A plan exists: from
tracking-plan, the target matrix intracking-audit, or a clear request ("track messaging clicks on the business pages as an Ads lead"). - Fixes handed over by
event-auditorconsent-audit.
Inputs
accountwithgtmContainerIdandga4PropertyIdset (check withaccount_profile; thesetupskill adds them).- The plan: events, data-layer keys, audience split (path regex), GA4 measurement ID (for example
G-TEST123), which Ads actions exist and which to create, consent per tag. - Site work done: the data-layer pushes from the plan's contract are live (or ship in the same release). Link click triggers need no site work.
Steps
Call account_profile first. Read guide("gtm") (recipes, rules, publish checklist) and guide("measurement")
(success signal, live tests). Every write below is a preview first and applied only after a yes; with the user's
agreement you may preview a whole group (say, all variables), then apply them one by one. Record each returned ID:
later steps need them.
- Baseline.
gtm_overview: if the workspace already has unpublished changes nobody can explain, stop and ask; publishing would ship them too. Note the live version ID as the rollback target.gtm_listwithentity: "tags","triggers"and"variables"so nothing is built twice (pre-flight also blocks duplicate names). Check for a Conversion Linker: agclidwtag on All Pages (or a Google tag configured with theAW-ID). Without it the click ID isn't stored first-party and Safari/ITP conversions go unattributed. If Ads conversion tags exist or will be built and there is none, create it withgtm_upsert:entity: "tags",resource: { name: "Conversion Linker", type: "gclidw", firingTriggerId: ["2147479553"] }. - Prerequisites.
gtm_builtin_variableswithaction: "list", thenaction: "enable"with the missingtypes(for example["pagePath", "clickUrl"]). Conditions onPage Pathand every link click trigger need them.ga4_custom_dimensionswithaction: "create",parameterName,displayNamefor each parameter in the plan (checkaction: "list"first). Not retroactive: do it before publishing.ads_create_conversion_actionfor each new action (name,category,countingTypeONE_PER_CLICKfor leads, optionalvalue,currency,primary). After it's applied, note the printedconversionIdandconversionLabelfor step 5. Reuse existing actions where the plan says so (labels fromrun_gaql_query:SELECT conversion_action.id, conversion_action.name, conversion_action.tag_snippets FROM conversion_action).
- Data-layer variables.
gtm_buildwithrecipe: { kind: "datalayer_variable", name: "DLV - form_name", key: "form_name" }, one per key the tags send (form_name, lead_type, product, page_language, event_id; value and currency only when the site sends a real value). - Triggers. Note each
triggerId.- Data-layer events:
recipe: { kind: "custom_event_trigger", name: "CE - generate_lead - Business", event: "generate_lead", conditions: [{ variable: "Page Path", op: "matchRegex", value: "^/business/" }] }. - Link clicks:
recipe: { kind: "link_click_trigger", name: "Link - WhatsApp - Business", match: "whatsapp", conditions: [...] };matchis"whatsapp","tel","mailto",{ contains }or{ regex }. Cover every link variant the plan lists. - Audience split = two triggers with the same regex, the second with
negate: true. Two hand-written regexes drift apart and leave pages counted twice or never.
- Data-layer events:
- GA4 event tags.
recipe: { kind: "ga4_event_tag", name: "GA4 Event - generate_lead", eventName: "generate_lead", measurementId: "G-TEST123", params: { form_name: "{{DLV - form_name}}", lead_type: "{{DLV - lead_type}}", … }, triggerIds: [...] }. Map every parameter the plan reports on: GA4 event tags don't forward data-layer fields. - Ads conversion tags.
recipe: { kind: "ads_conversion_tag", name: "Ads - Business Lead - Form", conversionId: "<digits after AW->", conversionLabel: "<label>", triggerIds: [...] }, with the sametriggerIdsas the matching GA4 tag, or GA4 and Ads will disagree. Addvalue: "{{DLV - value}}"andcurrency: "{{DLV - currency}}"only when the site pushes a real value (per the plan's data-layer contract); otherwise omit both so the conversion action's default value applies. A tag-sent0overrides that default and records every conversion as worthless. - Consent. Add
consent: { required: [...] }to the recipes in steps 4–5 per the plan when creating them. Consent on an existing tag always goes throughgtm_upsertwithresource: { consentSettings: … }(the shallow merge keeps its parameters); nevergtm_buildwith anidfor consent, since an update removes every setting the recipe doesn't model. Types per tag: see theconsent-auditskill. - When
gtm_buildreturns "NOT BUILT (nothing changed)". Fix each listed prerequisite (enable the built-in it names, create the missing variable, use a real trigger ID, rename the duplicate) and retry the same recipe. Never fall back togtm_upsertto get around a pre-flight finding. - Cleanup. Pause junk tags (conversions on page views, GA4 events sent to the wrong hostname or property,
duplicates of what you just built) with
gtm_upsert:entity: "tags",id,resource: { paused: true }. Delete (gtm_delete) only when the user explicitly asks; it refuses while anything references the entity. - Review.
gtm_versionswithversionId: "workspace", shown to the user in full: added, removed and changed tags, triggers and variables against live. Anything unintended gets fixed before publishing. - Publish. On a yes,
gtm_publishwith a datedname(2026-10-15 lead tracking) andnoteslisting what changed. Tell the user the rollback:gtm_publishwithversionId= the live version noted in step 0. - Live check.
gtm_live_checkright after publish: every conversion label, GA4 event name and measurement ID must be in the servedgtm.js. Google's CDN can lag a few minutes; re-run before calling anything missing. - Key events. Once each event has fired at least once,
ga4_set_key_eventwitheventName,action: "create". Test matrix the user runs, one row per event × audience:
Event Audience page Action taken GA4 Realtime / DebugView Ads tag fired (network) Pass generate_lead a /business/pagereal form submit generate_lead with form_name, lead_type conversion label seen generate_lead a /consumer/pagereal form submit … and the business tag did not fire … - One real action per row, in a normal browser profile; headless browsers are filtered as bots by GA4 and blocked by reCAPTCHA.
- Ad blockers drop hits: one missing manual test isn't proof of breakage; retry without extensions.
- No cross-firing between audiences.
- The Ads action shows "Recording" after 24–48 hours.
- Delete test leads from the CRM.
- Hand-off. Bidding: one custom goal per audience with
ads_create_custom_goalandads_assign_custom_goalto that audience's campaigns; secondary actions withads_set_conversion_primary(seetracking-auditstep 6.4).
Output
- A build log: each step, the created IDs (variables, triggers, tags, conversion actions) and change IDs.
- The workspace diff that was approved, the published version name and ID, and the rollback version ID.
- The
gtm_live_checkresult and the test matrix, with pass/fail as the user reports back.
Never
- Never publish without showing the full workspace diff and getting a yes, and never publish unexplained changes someone else left in the workspace.
- Never bypass a "NOT BUILT" pre-flight finding with
gtm_upsert. - Never trigger on visible text or page views for a lead; never give a GA4 tag and its Ads tag different triggers.
- Never delete tags, triggers or conversion actions unless the user asks; pause or make secondary instead.
- Never call tracking broken from one headless or ad-blocked test.
- If the profile is read-only (no write tools), deliver the build plan as a list of exact recipes and tell the user
that building needs
npx google-marketing-agent accounts set <alias> writes trueand an MCP client restart.
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
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.

