martechdevs has been acquired by Growth and Analytics Partners LLC

Tracking plans and naming

Event naming convention

Sets and enforces event and property naming for GA4, GTM, Mixpanel, Amplitude, PostHog and Segment. Covers object_action snake_case from one vocabulary of objects and past-tense actions, display labels, typed property names, per-destination mappings checked against reserved names and length limits, lint rules with a no-dependency script and a review checklist, and renames that keep history readable and count each action once.

FreeVersion 0.1.0Reviewed 17 October 2026

Produces three things: naming rules with a controlled vocabulary (martech-context/naming-rules.md), a linted event and property list with the final name each destination receives, and, when a live name must change, a rename plan that keeps history readable and counts each action once.

When to use

Use this skill when:

  • New events need names, or a developer's proposed list needs review before release.
  • A team needs naming rules, an event taxonomy or an event dictionary, or wants existing events cleaned up.
  • Observed data shows one action under several names (Sign Up, sign_up, signUp) or one name meaning two moments.
  • One plan feeds GA4 plus Mixpanel, Amplitude, PostHog or a CDP, and names must survive every destination, tag and connector.
  • An event or property must be renamed, merged or retired without breaking trends, funnels or key events.

Use something else when:

  • The trigger, identifiers, typed contract and acceptance tests of an event are the question: use the tracking-plan-builder skill. This skill names; that skill specifies.
  • Campaign or UTM values: utm-convention-and-registry. Ad platform object names: campaign-naming-convention.
  • Choosing which outcomes become GA4 key events or Ads conversions: conversion-goals-and-key-events.
  • Moving history from one analytics tool to another: analytics-migration.
  • Auditing a GTM container beyond its event names: gtm-container-audit.
  • Writing SDK code or editing a vendor's tracking plan: hand off to the vendor's own skill or MCP server (see Boundaries).

If a skill named here is not installed, stop at that decision and hand it to the user with the evidence gathered.

Inputs

Read these first if they exist, before asking anything:

  • martech-context/naming-rules.md: existing conventions and vocabulary. Extend it; never start a second one.
  • martech-context/stack.md: every destination, CDP, tag manager and connector in the path, and every field that rewrites names (such as the Lowercase Event Name field on each Segment GA4 Custom Event mapping).
  • martech-context/tracking-plan/ and data-dictionary.md: existing events and properties, so a new name does not duplicate one.
  • martech-context/decisions.md: earlier naming exceptions.

Then gather what is missing:

  • The raw names as emitted or observed, unedited: code, a GA4 events report, Mixpanel Lexicon or Amplitude Data export, or a warehouse event_name list with producer and app version.
  • For GA4 on web: a GTM container export, or a read-only list of GA4 Event tags with their Event Name and triggers (web and server containers). The name GA4 receives is usually set there.
  • For each name: who emits it (browser, server, iOS, Android, CDP route, GTM tag) and the moment it fires.
  • Property names with types, from a sample payload of a test account.
  • For a rename: the consumers of the old name and the release dates or app versions available.

Never ask for, print or store credentials or customer records. Sample payloads come from test accounts or are redacted first.

Procedure

1. Decide whether to change the convention at all

  • Keep the existing taxonomy when at least 95% of distinct names, or of event volume, already follow one pattern (house default; agree it with the data owner). Map it per destination, fix the rest as individual renames, and lint the final names. Do not migrate a working Title Case or camelCase taxonomy only for style.
  • Below that, or with no convention, adopt the default below and write it down.
  • Default for a new multi-tool implementation: lowercase ASCII snake_case, <object>_<past-tense action>, 40 characters at most, starting with a letter. It passes GA4 unchanged and fits Mixpanel's and Amplitude's object-verb guidance. Title Case becomes the display label. Vendor styles (Title Case with spaces, PostHog's colon) are compared in references/platform-constraints.md.

2. Write the vocabulary before naming anything

  • Objects: singular nouns from the product's domain (workspace, report_export, member_invitation), each with a one-line definition. Two words only when one is ambiguous.
  • Actions: past-tense verbs for completed facts, each with a definition. Start from assets/actions.txt; see assets/example-acme-objects.txt for an object list.
  • One term per concept. List forbidden synonyms (removed when deleted is chosen, cancelled when canceled is chosen) so they are not re-added.
  • Fill assets/naming-rules-template.md as the proposed naming-rules.md. For the lint script, copy each vocabulary section's backticked terms into temporary objects.txt and actions.txt files outside martech-context/, one per line, plus a forbidden: removed=deleted, ... line.

3. Name each event from the fact it records

  • Name the committed state change, not the gesture. The click is report_export_requested at most; report_export_succeeded is the outcome.
  • Split _requested, _succeeded and _failed only when the distinction drives a decision; join them with a job or attempt ID property. Otherwise one event.
  • Variants are properties: report_export_succeeded with export_format: pdf, not one event per format. Same for plans, steps, locations, versions, dates, locale, interaction method (a shortcut and a button share one event) and actor (actor_type keeps admin actions out of customer activation).
  • Names come from the vocabulary, never from UI copy or a translated label. One counting unit per name: a batch job and the files it produces are two events.
  • No destination, environment or release words in names (ga_, test, new, v2).
  • A name already used by another producer for a different moment is a defect, not a naming choice. Ask each producer when it fires.
  • Map to a GA4 recommended event (sign_up, purchase, generate_lead) only when the trigger matches Google's meaning and the required parameters exist (purchase needs transaction_id and items; currency whenever value is set). Keep the business name as canonical and record the GA4 name as a destination mapping.

4. Name and type the properties

Rules, context properties and per-tool reserved names: references/property-naming.md. The ones that break reports most often:

  • One property name, one type and one meaning across all events and producers.
  • Suffixes carry meaning: _id (string), _at (UTC timestamp), is_ or has_ (boolean), units for durations and sizes, money as amount plus ISO 4217 currency.
  • Enumerated values are listed lowercase codes with an explicit unknown policy; unknown is never silently mapped to a real value.
  • Event-time copies of profile traits get explicit names (plan_at_activation). Mixpanel joins the latest profile value onto past events; Amplitude records user properties at event time.
  • A parameter name valid in GA4 can still be reserved elsewhere (bucket, time, distinct_id in Mixpanel; revenue, value, currency in Segment).

5. Map each destination and record the final names

  • For each canonical event, record the name each destination actually receives after every tag, connector and transformation (GTM web and server containers, Segment mappings, Protocols transformations).
  • GTM: record the dataLayer event and the GA4 Event Name as separate columns (the script ignores extra columns) and lint the Event Name values from the container. An Event Name of {{Event}} forwards raw dataLayer names.
  • Segment's GA4 Cloud destination sends through the Measurement Protocol. Its Custom Event action replaces spaces with underscores and lowercases only where that mapping's Lowercase Event Name field is true.
  • Route an event only to destinations with a named use.
  • Write the mapping as a CSV (canonical_name,destination,destination_name); example: assets/example-acme-mapping.csv.

6. Lint

Run the rule set over the raw list, the property list and the mapping. Call the script by the absolute path of this skill's scripts/ folder, with the vocabulary files from step 2. Rules, severities and output format: references/linter-rules.md.

python3 <skill folder>/scripts/lint_event_names.py names.txt --objects objects.txt --actions actions.txt
python3 <skill folder>/scripts/lint_event_names.py properties.txt --kind property
python3 <skill folder>/scripts/lint_event_names.py mapping.csv --kind mapping --objects objects.txt --actions actions.txt
  • The script needs only Python 3 and changes nothing; its reserved lists are dated. If it cannot run, apply the rules by reading the list and count characters with code.
  • Then apply the manual rules R01 to R07 (wrong fact, two meanings, intent, variants, synonyms, personal data, style-only migrations).
  • Optional GA4 check: send each GA4 destination event with its mapped parameters to the Measurement Protocol validation server (/debug/mp/collect, which collects nothing) with placeholder IDs. Pass: empty validationMessages. Details in the platform reference.
  • Approval rule: zero unresolved errors; every warning fixed or given a one-line reason in the registry.

7. Review

Walk references/review-checklist.md with the person who knows where success is committed in code and the person who owns the decision the event serves. Confirm one received test payload per destination before approval: DebugView for gtag.js, GTM and Firebase; the validation server, then Realtime or BigQuery, for Measurement Protocol senders such as Segment GA4 Cloud.

8. Rename or merge live names safely

Classify first: label only, raw rename with the same meaning, duplicates, semantic change, or retirement. Per-platform procedures: references/renames-and-migrations.md.

  • Label only: a display name in Mixpanel Lexicon or Amplitude Data (UI only).
  • Raw rename or duplicates: inventory consumers, add the new name to every blocking schema first, switch each producer at a recorded boundary (deploy time, GTM version publish time, app version), then pick the history method with the overlap test.
  • Overlap test, before any Mixpanel merge, Amplitude transformation, PostHog action or warehouse union (each adds the two series for all history). Evidence: one recent full week of daily count(old), count(new) and their sum against the source-of-truth table, plus an entity-ID join.
    • Disjoint (house default: the sum within 2% of the source of truth every day, no entity ID under both names): merge.
    • Overlapping, and the authoritative series has always fired (a backend event): keep it, repoint reports, then hide the duplicate or label it "(duplicate, retired)". Never merge.
    • Overlapping, and the new series starts at the boundary: date split; exclude old-version traffic after the boundary.
  • GA4 never rewrites history: report old before the boundary and new after. Copy key-event status, counting method and default value to the new name before release. Change a GTM-set name in a new container version and a Segment GA4 Cloud name in its mapping; Modify event is a client-side bridge that never applies to Measurement Protocol traffic. Never use Create event to rename.
  • Default is no dual emission. If a consumer forces it, route the legacy copy only to that consumer, set an end date and give each copy its own vendor dedupe key (details in the reference). GA4 deduplicates only purchase with the same transaction_id on web streams; never send an empty transaction_id.
  • Semantic change: a new name and an annotated break, never the old name with a new meaning.

9. Propose the files

Show the user the proposed changes and wait for approval before writing:

  • martech-context/naming-rules.md (rules and vocabulary)
  • registry or tracking-plan entries with display names, destination names, producers and lint exceptions (example: assets/example-acme-registry.yaml)
  • decisions.md entries for exceptions and convention changes
  • for a rename: the rename plan from the renames reference, with the overlap result

Common failure modes

  • Case and separator variants of one action (Report Created, report_created, reportExported). Detect: N17 on the observed list; one action split across events in each tool.
  • One name, two moments (click on web, committed record on backend). Detect: the event to source-of-truth ratio above 1.05 for 7 days (house default); volume split by producer.
  • Values or UI copy in names (plan_selected_pro, onboarding_step_3_completed, a translated label). Detect: N13 and N11; distinct names growing with the catalogue; one object under several labels after a copy or language change.
  • GTM passthrough: a GA4 Event tag whose Event Name is {{Event}} or a lookup table sends dataLayer names into GA4, and renaming a dataLayer event silently stops its Custom Event trigger. Detect: a variable in an Event Name field of the export; unplanned camelCase names in GA4; zero volume after a dataLayer change.
  • Default or autocaptured events duplicating a custom one (GA4 enhanced measurement form_submit beside form_submitted). Detect: each destination's enabled default events listed beside custom events with the same meaning; keep one, recorded in decisions.md.
  • GA4 silent drops and reserved names: names or parameter names over 40 characters, the 26th parameter, page_view reused for a product event, Purchase, ga_, firebase_, $. Detect: N04, N08, N09, M09, M10; the name or parameter missing in GA4.
  • Display name masking a bad raw name. Detect: Mixpanel Data Standards shows compliant while raw names fail the lint.
  • Rename that dropped the event, doubled counts or froze charts. Detect: zero volume for the new name under a plan that drops unplanned events (Amplitude, Segment, RudderStack); a merge, action or metric over names that failed the overlap test; saved charts still filtered on the old raw name after cutover.

Worked example

Acme Reports (fictional) sends events from a web app (Google tag, Segment with GA4 Cloud), an iOS app and a backend to Mixpanel and GA4. Full review: assets/example-acme-review.md; the raw list assets/example-acme-events-input.txt gives 8 errors and 10 warnings. Points worth copying:

  • Sign Up (click), signup_completed (iOS screen load) and user_registered (backend commit) were three names for two moments. The overlap test showed signup_completed duplicates user_registered, which has always fired, so iOS stops sending it and it is hidden, never merged. Report Created (web) overlapped report_created (backend) the same way.
  • report_exported_pdf and reportExported become report_export_succeeded with export_format, read by date split.
  • subscription_cancelled (button) and subscription_canceled (webhook) were two facts, not a spelling clash.
  • The new mapping lints with zero errors and two warnings, each with a reason; the key-event question goes to the conversion owner.

Acceptance checks

  • Naming rules: naming-rules.md states the pattern, length budget, spelling, object and action vocabularies with definitions, forbidden synonyms and the change process. Pass: no template placeholder remains, and the vocabulary files used for linting list exactly the same terms.
  • Lint: the raw list, property list and mapping were linted. Pass: zero unresolved errors; every warning has a fix or a one-line reason in the registry.
  • Reserved lists: the GA4 reserved names page and the destinations' limits were fetched on the day of approval. Pass: URL and date recorded; no difference from the script's lists, or the script lists were updated.
  • Destinations: every canonical event has the final received name per destination, including GTM Event Name values. Pass: no M-rule errors; one received test payload per destination matches the planned name and property types.
  • Meaning: every event has one producer moment and a counting unit. Pass: no name is emitted by two producers at different moments.
  • Renames: each has a classification, consumer inventory with owners, boundary per producer and per-tool history plan. Pass: the rename plan is complete and approved, no metric counts both names, and every merged pair has a disjoint overlap result with its evidence.
  • Approval: the user approved the files before they were written. Pass: nothing in martech-context/ or any vendor tool changed without approval.

Boundaries

  • This skill proposes names, rules, mappings and rename plans. It does not change code, tags, GTM containers, Lexicon, Amplitude Data, GA4 admin settings or CDP transformations. Every live change is a draft change list that stops for human approval.
  • Display-name edits, merges, blocks, deletes and transformations change shared configuration for every user; data sent while a Mixpanel or Amplitude block is active is never stored.
  • Hand-offs, with read-only modes where they exist (tool lists in the platform reference):
    • GA4: Google's GA4 MCP server (Experimental, analytics.readonly scope) for event names and custom dimensions. Modify event, key events and custom definitions are changed in the GA4 interface by a person with the required role.
    • GTM: the gtm-container-audit skill, or the Tag Manager API with the tagmanager.readonly scope. Changes go into a workspace for a person to publish.
    • Mixpanel: MCP read tools Get-Events, List-Properties; write tools only from an approved change list (no read-only mode is documented). Mixpanel's manage-lexicon skill cleans Lexicon metadata.
    • Amplitude: MCP with a read role (get_amp_taxonomy, get_transformations); taxonomy changes on a branch. Its taxonomy and tracking-plan-audit skills audit naming.
    • PostHog: MCP in read-only mode (x-posthog-read-only: true).
    • Segment: Twilio's MCP only searches docs; transformations and GA4 Cloud mappings are changed in the Segment app by a workspace owner or source admin.

Live docs

Platform settings, limits and menu paths change. Before stating any parameter name, limit, quota or UI path:

  • Fetch the current page from the vendor docs MCP server or llms.txt listed in sources.yaml, or open the canonical URL.
  • If the live page disagrees with this skill, follow the live page and tell the user what changed.
  • Cite the URL you used.

Most used: the GA4 naming, limits, modify event, key events and validation pages; GTM event tag, trigger and versions; Mixpanel Lexicon and Data Standards; Amplitude transformations and data settings; PostHog best practices and capture events; Segment's GA4 destination and transformations. Every limit here was checked on 2026-10-17. Verify at run time: whether GTM Custom Event triggers match case sensitively, whether the validation server accepts a placeholder measurement_id, and whether Create event applies to Measurement Protocol traffic.

Book a Free Call

Thirty minutes on your stack and what it needs. Free, and no pitch.

Thirty minutes, and you leave with a plan

We look at what you have, what it is costing you and what to do about it first.

  • 30 minutes
  • Video call, link on booking
  • No obligation

What we'll cover

  • Your current stack and where it hurts
  • Quick wins we can ship first
  • An integration roadmap
  • Timeline, scope and next steps

Calendar not loading? Open it in a new tab or email hello@martechdevs.com.