Analytics and tracking skill 04 of 6
GA4 measurement setup
A GA4 property is usually set up once, left on its defaults, and trusted for months before anyone notices the gaps. This skill makes an AI agent configure a property in a fixed order, justify each setting against the tracking plan, and flag the settings that delete data before touching them.
By Afeez Adebayo, Marketing, SEO & Growth Expert with 10+ years of experience.
Created 6 November 2026. Updated 6 November 2026. Free to use under CC BY 4.0.
A GA4 property is usually set up once, left on its defaults, and trusted for months before anyone notices the gaps. By then the retention window has already dropped the history, a custom dimension reads "(not set)" for the period before it was registered, and a payment redirect has been quietly splitting sessions. None of that is recoverable after the fact. This skill makes an AI agent configure a GA4 property in a fixed order, justify each setting against the plan, and flag the few settings that destroy data before touching them.
The job is configuration, not design and not analysis. It takes an agreed tracking plan and turns it into a property that collects what the plan asks for: events that use the recommended names where they exist, custom dimensions registered before anything depends on them, retention and identity chosen on purpose, personal data kept out at the source, and only the business-critical events marked as key events. Taxonomy, tag deployment, consent and QA each belong to a sibling skill, named below.
When to use this skill, and when not to
Use this skill to configure a new GA4 property, to audit an existing one against its plan, or to fix a specific configuration fault: a dimension that will not appear in reports, retention set too short, self-referrals polluting attribution, or events that duplicate what GA4 already collects. It fires on GA4 property or data-stream setup, recommended versus custom events, custom dimensions or metrics, "(not set)", data retention, key events or conversions, referral exclusions, Google Signals, User-ID, and linking GA4 to BigQuery or Google Ads.
Do not use it to design the event names and properties in the first place, which is the sibling event-tracking-plan and which this skill configures from. Do not use it to build the tags that send the events, which is gtm-container-management. Do not use it to configure consent, which is consent-mode-tracking. Do not use it to prove the tracking fires, which is analytics-qa-validation. Do not use it for ad-platform conversions and the Conversions API, which is conversion-tracking-capi, or to analyse data that is already trusted, which is funnel-analysis or cohort-retention-analysis. If there is no tracking plan to configure from, stop and build one first; configuring a property against a guess produces a tidy property full of the wrong data.
Inputs the agent must have before starting
Ask for these in one message, and do not assume them:
- The tracking plan: the events and properties the property is meant to collect, with their names and types. Without it there is no definition of correct.
- Access to the GA4 property and its data streams, and whether it is a standard or a 360 property, because the limits and retention options differ.
- The surfaces in scope (web, iOS, Android) so the right number of data streams is set, one per surface.
- The business-critical actions that should be key events, and who signs off on that list, because marking a key event changes reporting.
- The domains involved: the main site, any subdomains, and third parties that redirect users back (payment, SSO, booking), so referral and cross-domain settings are correct.
- Whether a durable user identifier exists and may be sent, and whether BigQuery export is wanted, because both are set-up-time decisions that are not retroactive.
- Any personal data that currently reaches URLs or event parameters, so it can be removed at the source before collection continues.
If this is a fix for one symptom rather than a full setup, scope the work to that symptom and say so, rather than reconfiguring the whole property around one broken report.
Raw SKILL.md file
This is the exact file agents read, including the credit header and licence notice. Save it as ga4-measurement-setup/SKILL.md.
---
name: ga4-measurement-setup
description: Configures a Google Analytics 4 property from an agreed tracking plan so the collected data is complete, attributed correctly, and free of personal data, covering the event model, custom dimension registration, data retention, identity, data-stream settings, and key events. Use when the request mentions setting up GA4, a GA4 property or data stream, recommended versus custom events, GA4 custom dimensions or metrics, "(not set)" in reports, data retention, key events or conversions in GA4, referral exclusions, Google Signals, User-ID, or linking GA4 to BigQuery or Google Ads. Do NOT use for designing the event taxonomy (event-tracking-plan), deploying tags through a tag manager (gtm-container-management), configuring consent (consent-mode-tracking), validating that tracking fires (analytics-qa-validation), ad-platform conversions and the Conversions API (conversion-tracking-capi), or analysing the data once collected (funnel-analysis, cohort-retention-analysis).
license: CC BY 4.0. Free to use and adapt with credit to Afeez Adebayo.
metadata:
author: Afeez Adebayo
website: https://afeezadebayo.com
linkedin: https://www.linkedin.com/in/afeez-adebayo/
source: https://afeezadebayo.com/skills-md/data/analytics-tracking/ga4-measurement-setup/
category: data
subcategory: analytics-tracking
version: 1.0.0
created: 6 November 2026
updated: 6 November 2026
---
# GA4 measurement setup
A GA4 property is usually set up once, left on its defaults, and trusted for months before anyone notices the gaps. By then the retention window has already dropped the history, a custom dimension reads "(not set)" for the period before it was registered, and a payment redirect has been quietly splitting sessions. None of that is recoverable after the fact. This skill makes an AI agent configure a GA4 property in a fixed order, justify each setting against the plan, and flag the few settings that destroy data before touching them.
The job is configuration, not design and not analysis. It takes an agreed tracking plan and turns it into a property that collects what the plan asks for: events that use the recommended names where they exist, custom dimensions registered before anything depends on them, retention and identity chosen on purpose, personal data kept out at the source, and only the business-critical events marked as key events. Taxonomy, tag deployment, consent and QA each belong to a sibling skill, named below.
## When to use this skill, and when not to
Use this skill to configure a new GA4 property, to audit an existing one against its plan, or to fix a specific configuration fault: a dimension that will not appear in reports, retention set too short, self-referrals polluting attribution, or events that duplicate what GA4 already collects. It fires on GA4 property or data-stream setup, recommended versus custom events, custom dimensions or metrics, "(not set)", data retention, key events or conversions, referral exclusions, Google Signals, User-ID, and linking GA4 to BigQuery or Google Ads.
Do not use it to design the event names and properties in the first place, which is the sibling `event-tracking-plan` and which this skill configures from. Do not use it to build the tags that send the events, which is `gtm-container-management`. Do not use it to configure consent, which is `consent-mode-tracking`. Do not use it to prove the tracking fires, which is `analytics-qa-validation`. Do not use it for ad-platform conversions and the Conversions API, which is `conversion-tracking-capi`, or to analyse data that is already trusted, which is `funnel-analysis` or `cohort-retention-analysis`. If there is no tracking plan to configure from, stop and build one first; configuring a property against a guess produces a tidy property full of the wrong data.
## Inputs the agent must have before starting
Ask for these in one message, and do not assume them:
1. The tracking plan: the events and properties the property is meant to collect, with their names and types. Without it there is no definition of correct.
2. Access to the GA4 property and its data streams, and whether it is a standard or a 360 property, because the limits and retention options differ.
3. The surfaces in scope (web, iOS, Android) so the right number of data streams is set, one per surface.
4. The business-critical actions that should be key events, and who signs off on that list, because marking a key event changes reporting.
5. The domains involved: the main site, any subdomains, and third parties that redirect users back (payment, SSO, booking), so referral and cross-domain settings are correct.
6. Whether a durable user identifier exists and may be sent, and whether BigQuery export is wanted, because both are set-up-time decisions that are not retroactive.
7. Any personal data that currently reaches URLs or event parameters, so it can be removed at the source before collection continues.
If this is a fix for one symptom rather than a full setup, scope the work to that symptom and say so, rather than reconfiguring the whole property around one broken report.
## Workflow
### Step 1. Confirm the plan and the property scope
Load the tracking plan. Confirm the property type (standard or 360) and list the data streams needed, one per surface. A single web property should not have a stream per page or per campaign; it has one web stream. Everything below configures the property to match the plan, so if the plan and the live property disagree on an event or property name, treat the plan as the source of truth and note the mismatch.
### Step 2. Map each planned event to the GA4 model
GA4 has four kinds of event, and the right one is almost always the least custom option that fits.
- If GA4 already collects the interaction automatically (for example `first_visit`, `session_start`, `user_engagement`) or through enhanced measurement (`scroll`, `click`, `file_download`), use that and do not send a second event for the same thing. If a manual event and an automatic one both cover an interaction, keep one and disable the other; running both is the most common cause of doubled counts.
- If a recommended event name matches the interaction, use the recommended name exactly as published (for example `purchase`, `login`, `sign_up`). Recommended names have predefined parameters and populate prebuilt reports, which custom names do not.
- Create a custom event only when no automatic, enhanced or recommended event fits.
Apply the hard rules: event names are case sensitive, so `Sign_Up` and `sign_up` are different events; keep one casing (the plan decides the grammar, see `event-tracking-plan`). Event names have a 40-character limit. Do not use the reserved prefixes `ga_`, `google_` or `firebase_`, or the reserved event names; verify the current reserved list before relying on it. Keep within the per-event parameter limit (verify the current number in the documentation). Events must be sent below the Google tag, or GA4 will not process them.
### Step 3. Register custom dimensions and metrics before anything depends on them
Sending a parameter is not enough. A parameter that is not registered as a custom dimension or metric in the GA4 interface will not appear in reports, and the registration is not retroactive: the period before you registered it shows "(not set)". So register every parameter the plan needs in reports, with a name and scope that match the tagging, before release.
Decision rules:
- If a parameter must appear in the GA4 interface, register it. If it is only ever queried in BigQuery, do not spend a dimension slot on it.
- Standard properties cap custom dimensions and metrics (verify the current limits before relying on them; treat the slots as scarce and reserve them for parameters that earn a report).
- Prefix any numeric-looking identifier with a letter so GA4 stores it as text, not a number.
- Avoid high-cardinality dimensions. A dimension that takes more than 500 distinct values in a single day degrades the accuracy of reports that use it and pushes rows into an "(other)" bucket. Bucket continuous values into ranges and register the bucketed value, not the raw one.
### Step 4. Set data retention and identity on purpose
Event data retention defaults to the shortest option, which is not enough for year-on-year analysis and is not applied retroactively if you raise it later. Set event data retention to 14 months on a standard property, or the maximum on 360, at setup. Leave "reset user data on new activity" on if you want an active user's data to persist rather than expire from their last visit.
Decreasing retention is destructive: data older than the new window is deleted at the next monthly deletion run, with only a 24-hour grace period to revert. Treat any decrease as an irreversible action and get explicit human confirmation before making it.
Choose the reporting identity deliberately. For a site without logins or user IDs, device-based identity behaves most like the older model and avoids surprise modelling. Google Signals adds cross-device matching but applies modelling and data thresholds that can hide rows, so turn it on for a reason, not by reflex. If a durable user identifier exists and may be collected, send it as User-ID, and hash any personal data before it is used as an identifier.
### Step 5. Configure the data stream so attribution and privacy hold
- Add unwanted referrals for every third party that redirects users back to the site (payment processors, SSO providers, your own short-link and auth subdomains). Left out, they start new sessions and send conversions to a referral bucket instead of the original source.
- Configure your domains so sessions survive across subdomains and cross-domain hops. Deep cross-domain tagging through the container belongs to `gtm-container-management`; this step is the GA4-side domain list.
- Keep personal data out. GA4 cannot exclude a single URL query parameter and cannot later delete one parameter in isolation; a deletion request wipes the whole `page_location` value. So strip personal data at the source and enforce a parameter allowlist in the tag manager (see `gtm-container-management`) so only approved parameters reach GA4.
- Filter internal and developer traffic. Define the filters, but leave a new internal-traffic filter in Testing until you have confirmed it matches the right traffic; setting it Active removes that traffic from reports, so confirm first.
- Mark the agreed key events (conversions). GA4 caps the number of key events (verify the current cap). Mark only business-critical actions. Mark a micro-conversion as a key event only when an ad campaign is actually optimising for it. Marking or unmarking a key event changes reporting from that moment, so confirm the final list with the person who owns it.
### Step 6. Link products, state the cost, and verify
Link BigQuery early, because the export begins only when linked and does not backfill; standard export has a free tier and then charges, so state that cost rather than enabling it silently. Link Google Ads and any other Google Marketing Platform products in use, and enable auto-tagging so campaign data classifies correctly.
Then verify, in this order: the event appears in DebugView with its parameters, then in Realtime, then, after processing, in standard reports; each registered custom dimension resolves to real values rather than "(not set)"; the key-events report shows the events you marked; and the self-referrals have stopped. Do not declare setup done on Realtime alone, because a filter can still drop the data before it reaches standard reports. Deep validation and monitoring are the job of `analytics-qa-validation`.
## Worked example
A SaaS site has an agreed plan with `sign_up`, `login`, a custom `trial_started` event, and a `plan_tier` property, and it wants trials counted as a conversion.
Step 2 maps `sign_up` and `login` to the recommended names and keeps `trial_started` as a custom event, since nothing recommended fits. Step 3 registers `plan_tier` as an event-scoped custom dimension before release; without that it would read "(not set)" on every report. Step 4 sets retention to 14 months, leaves reset-on-new-activity on, and chooses device-based identity because the marketing site has no login. Step 5 adds the Stripe checkout domain and the `auth.` subdomain as unwanted referrals, which had been starting new sessions and sending sign-ups to a referral source; it marks `sign_up` and `trial_started` as key events, declines to mark `login` because it is not a business outcome, and raises the client's request to also mark `pricing_page_view` as a micro-conversion worth marking only if a campaign optimises for it, leaving it unmarked for now. Step 6 links BigQuery and states the export cost.
Verification: `trial_started` fires in DebugView with `plan_tier` populated, the key-events report shows both marked events the next day, and the referral spike from Stripe is gone. The headline is that two settings nobody would have noticed, the missing dimension registration and the missing referral exclusions, would each have quietly corrupted a core report.
## Templates you can use verbatim
Event-to-model mapping (one row per planned event):
```
planned event | GA4 category (auto / enhanced / recommended / custom) | GA4 name | notes
sign up | recommended | sign_up | predefined name, prebuilt reporting
trial start | custom | trial_started | no recommended match; register plan_tier
form submit | enhanced | form_submit | enhanced measurement; do not also send a manual one
```
Custom dimension registration row (register before release):
```
parameter: plan_tier
scope: event (event or user)
ga4 dimension name: Plan tier
needed in UI? yes (if no and only in BigQuery, do not register)
cardinality check: < 500 distinct values/day? yes
numeric-looking id? no (if yes, prefix with a letter)
```
Property setup checklist:
```
[ ] One data stream per surface, matched to the plan
[ ] Every event mapped to the least custom category that fits; recommended names used where they exist
[ ] Event names <= 40 chars, consistent casing, no ga_/google_/firebase_ prefix
[ ] Every parameter needed in reports registered with matching name and scope, before release
[ ] Retention set to 14 months (or 360 max); any decrease confirmed by a human
[ ] Reporting identity chosen deliberately; User-ID hashed if used
[ ] Unwanted referrals and domains configured; internal/developer traffic filtered (filter in Testing first)
[ ] Only business-critical events marked as key events, within the cap, sign-off obtained
[ ] No PII in URLs or parameters; parameter allowlist in place in the tag manager
[ ] BigQuery and product links set, export cost stated
[ ] Verified in DebugView, Realtime, and standard reports (not Realtime alone)
```
Audit prompt: "Here is the tracking plan and access to the GA4 property. Check each event maps to the least custom GA4 category that fits, every reported parameter is registered with matching scope, retention is 14 months, referral exclusions cover payment and auth domains, and no PII reaches URLs or parameters. List each gap and whether fixing it is retroactive."
## Failure modes and anti-patterns
1. Sending a parameter and never registering it. You spot it when a report shows "(not set)" or the dimension is missing from the list. Fix it by registering the dimension with a matching name and scope before release, and recover the pre-registration period from BigQuery if it was linked.
2. Leaving retention at the default. You spot it when an exploration cannot go back a year. Fix it by setting 14 months (or the 360 maximum) at setup, because raising it later does not backfill. Never decrease retention without human sign-off, because the decrease deletes data.
3. Personal data in URLs or event parameters. You spot it when an email or a name appears in `page_location` or a parameter. Fix it by stripping the data at the source and enforcing a parameter allowlist, and note that GA4 cannot remove a single parameter later; a deletion request wipes the whole value.
4. Duplicating an event GA4 already collects. You spot it when a metric reads roughly double, for example two `form_submit` events per submission. Fix it by choosing one source, automatic or manual, and disabling the other.
5. A high-cardinality custom dimension. You spot it when a dimension has thousands of values, accuracy warnings, or large "(other)" rows. Fix it by bucketing the values into ranges under 500 distinct per day and registering the bucketed value.
## Quality bar for the setup
Before handing over, confirm every item:
- Every planned event is mapped to the least custom GA4 category that fits, recommended names are used where they exist, and names are within 40 characters with no reserved prefix.
- Every parameter that must appear in the interface is registered with a matching name and scope, before release.
- Retention is set deliberately to 14 months or the 360 maximum, and any decrease was confirmed by a human.
- No personal data reaches URLs or parameters, and a parameter allowlist is in place.
- Referral exclusions and domains are configured, and internal and developer traffic are filtered.
- Only business-critical events are marked as key events, within the current cap, with sign-off.
- BigQuery and product links are set, and the export cost was stated rather than assumed.
- The setup was verified in DebugView, Realtime and standard reports, not Realtime alone.
- Every version-dependent limit (custom dimensions, key events, parameters per event) was checked against current documentation.
## Tool-specific appendix
```
GA4 specifics (verify version-dependent numbers before relying on them)
- Event categories: automatically collected, enhanced measurement, recommended, custom. Prefer the least
custom that fits; recommended names populate prebuilt reports.
- Hard rules: event names case-sensitive, 40-char limit; reserved prefixes ga_, google_, firebase_ and
reserved event names are not allowed; events must sit below the Google tag.
- Processing limits: up to 20 events per batch, 16 KB per send (an oversized batch is not processed),
events arriving more than 72 hours after they fired are ignored, key events are sent immediately.
- Custom dimensions/metrics: must be registered in the UI to appear in reports; not retroactive
("(not set)" before registration); standard-property slot limits are capped (verify current numbers);
prefix numeric-looking IDs with a letter; bucket dimensions above ~500 distinct values/day.
- Retention: 2 or 14 months (standard); 26/38/50 on 360; raising is applied to data not yet deleted,
lowering deletes older data at the next monthly run with a 24-hour revert window; affects explorations
and funnels, not standard aggregated reports.
- Identity: device-based is closest to the old model for sites without login; Google Signals adds
cross-device matching but applies modelling and data thresholds; User-ID needs a durable id, hashed if
derived from PII.
- BigQuery export: begins only when linked, is not retroactive, has a free tier then charges.
```
## Sources
- Google, GA4 events developer guide (the four event categories, recommended versus custom, events below the Google tag). Last verified 6 November 2026.
- Google, GA4 "about events" (batching of up to 20 events, 16 KB send limit, 72-hour arrival window, key events sent immediately, use existing events before custom). Last verified 6 November 2026.
- Google Analytics Help, data retention (2 and 14 month options, 360 options, retroactivity of raising versus lowering, 24-hour revert, reset on new activity, effect on explorations only). Last verified 6 November 2026.
- Louder, GA4 setup mistakes (retention default, PII in URLs and the GTM allowlist, custom dimension registration and the 25-dimension note, numeric-id prefixing, key events, referral exclusion and domain configuration, product linking, identity). Last verified 6 November 2026; dimension and key-event limits are version-dependent, so re-check the documentation.
- Search Engine Journal, GA4 mistakes (retention and reset-on-new-activity, high-cardinality dimensions above 500 values per day and bucketing, BigQuery linking and export sampling, reporting identity and modelling). Last verified 6 November 2026.
- Related skills: event-tracking-plan (the taxonomy this configures), gtm-container-management (deploying the tags and the parameter allowlist), consent-mode-tracking (consent configuration), analytics-qa-validation (proving it fires), conversion-tracking-capi (ad-platform conversions), funnel-analysis (analysis once the data is trusted).
Workflow
Step 1. Confirm the plan and the property scope
Load the tracking plan. Confirm the property type (standard or 360) and list the data streams needed, one per surface. A single web property should not have a stream per page or per campaign; it has one web stream. Everything below configures the property to match the plan, so if the plan and the live property disagree on an event or property name, treat the plan as the source of truth and note the mismatch.
Step 2. Map each planned event to the GA4 model
GA4 has four kinds of event, and the right one is almost always the least custom option that fits.
- If GA4 already collects the interaction automatically (for example
first_visit,session_start,user_engagement) or through enhanced measurement (scroll,click,file_download), use that and do not send a second event for the same thing. If a manual event and an automatic one both cover an interaction, keep one and disable the other; running both is the most common cause of doubled counts. - If a recommended event name matches the interaction, use the recommended name exactly as published (for example
purchase,login,sign_up). Recommended names have predefined parameters and populate prebuilt reports, which custom names do not. - Create a custom event only when no automatic, enhanced or recommended event fits.
Apply the hard rules: event names are case sensitive, so Sign_Up and sign_up are different events; keep one casing (the plan decides the grammar, see event-tracking-plan). Event names have a 40-character limit. Do not use the reserved prefixes ga_, google_ or firebase_, or the reserved event names; verify the current reserved list before relying on it. Keep within the per-event parameter limit (verify the current number in the documentation). Events must be sent below the Google tag, or GA4 will not process them.
Step 3. Register custom dimensions and metrics before anything depends on them
Sending a parameter is not enough. A parameter that is not registered as a custom dimension or metric in the GA4 interface will not appear in reports, and the registration is not retroactive: the period before you registered it shows "(not set)". So register every parameter the plan needs in reports, with a name and scope that match the tagging, before release.
Decision rules:
- If a parameter must appear in the GA4 interface, register it. If it is only ever queried in BigQuery, do not spend a dimension slot on it.
- Standard properties cap custom dimensions and metrics (verify the current limits before relying on them; treat the slots as scarce and reserve them for parameters that earn a report).
- Prefix any numeric-looking identifier with a letter so GA4 stores it as text, not a number.
- Avoid high-cardinality dimensions. A dimension that takes more than 500 distinct values in a single day degrades the accuracy of reports that use it and pushes rows into an "(other)" bucket. Bucket continuous values into ranges and register the bucketed value, not the raw one.
Step 4. Set data retention and identity on purpose
Event data retention defaults to the shortest option, which is not enough for year-on-year analysis and is not applied retroactively if you raise it later. Set event data retention to 14 months on a standard property, or the maximum on 360, at setup. Leave "reset user data on new activity" on if you want an active user's data to persist rather than expire from their last visit.
Decreasing retention is destructive: data older than the new window is deleted at the next monthly deletion run, with only a 24-hour grace period to revert. Treat any decrease as an irreversible action and get explicit human confirmation before making it.
Choose the reporting identity deliberately. For a site without logins or user IDs, device-based identity behaves most like the older model and avoids surprise modelling. Google Signals adds cross-device matching but applies modelling and data thresholds that can hide rows, so turn it on for a reason, not by reflex. If a durable user identifier exists and may be collected, send it as User-ID, and hash any personal data before it is used as an identifier.
Step 5. Configure the data stream so attribution and privacy hold
- Add unwanted referrals for every third party that redirects users back to the site (payment processors, SSO providers, your own short-link and auth subdomains). Left out, they start new sessions and send conversions to a referral bucket instead of the original source.
- Configure your domains so sessions survive across subdomains and cross-domain hops. Deep cross-domain tagging through the container belongs to
gtm-container-management; this step is the GA4-side domain list. - Keep personal data out. GA4 cannot exclude a single URL query parameter and cannot later delete one parameter in isolation; a deletion request wipes the whole
page_locationvalue. So strip personal data at the source and enforce a parameter allowlist in the tag manager (seegtm-container-management) so only approved parameters reach GA4. - Filter internal and developer traffic. Define the filters, but leave a new internal-traffic filter in Testing until you have confirmed it matches the right traffic; setting it Active removes that traffic from reports, so confirm first.
- Mark the agreed key events (conversions). GA4 caps the number of key events (verify the current cap). Mark only business-critical actions. Mark a micro-conversion as a key event only when an ad campaign is actually optimising for it. Marking or unmarking a key event changes reporting from that moment, so confirm the final list with the person who owns it.
Step 6. Link products, state the cost, and verify
Link BigQuery early, because the export begins only when linked and does not backfill; standard export has a free tier and then charges, so state that cost rather than enabling it silently. Link Google Ads and any other Google Marketing Platform products in use, and enable auto-tagging so campaign data classifies correctly.
Then verify, in this order: the event appears in DebugView with its parameters, then in Realtime, then, after processing, in standard reports; each registered custom dimension resolves to real values rather than "(not set)"; the key-events report shows the events you marked; and the self-referrals have stopped. Do not declare setup done on Realtime alone, because a filter can still drop the data before it reaches standard reports. Deep validation and monitoring are the job of analytics-qa-validation.
Worked example
A SaaS site has an agreed plan with sign_up, login, a custom trial_started event, and a plan_tier property, and it wants trials counted as a conversion.
Step 2 maps sign_up and login to the recommended names and keeps trial_started as a custom event, since nothing recommended fits. Step 3 registers plan_tier as an event-scoped custom dimension before release; without that it would read "(not set)" on every report. Step 4 sets retention to 14 months, leaves reset-on-new-activity on, and chooses device-based identity because the marketing site has no login. Step 5 adds the Stripe checkout domain and the auth. subdomain as unwanted referrals, which had been starting new sessions and sending sign-ups to a referral source; it marks sign_up and trial_started as key events, declines to mark login because it is not a business outcome, and raises the client's request to also mark pricing_page_view as a micro-conversion worth marking only if a campaign optimises for it, leaving it unmarked for now. Step 6 links BigQuery and states the export cost.
Verification: trial_started fires in DebugView with plan_tier populated, the key-events report shows both marked events the next day, and the referral spike from Stripe is gone. The headline is that two settings nobody would have noticed, the missing dimension registration and the missing referral exclusions, would each have quietly corrupted a core report.
Templates you can use verbatim
Event-to-model mapping (one row per planned event):
planned event | GA4 category (auto / enhanced / recommended / custom) | GA4 name | notes
sign up | recommended | sign_up | predefined name, prebuilt reporting
trial start | custom | trial_started | no recommended match; register plan_tier
form submit | enhanced | form_submit | enhanced measurement; do not also send a manual oneCustom dimension registration row (register before release):
parameter: plan_tier
scope: event (event or user)
ga4 dimension name: Plan tier
needed in UI? yes (if no and only in BigQuery, do not register)
cardinality check: < 500 distinct values/day? yes
numeric-looking id? no (if yes, prefix with a letter)Property setup checklist:
[ ] One data stream per surface, matched to the plan
[ ] Every event mapped to the least custom category that fits; recommended names used where they exist
[ ] Event names <= 40 chars, consistent casing, no ga_/google_/firebase_ prefix
[ ] Every parameter needed in reports registered with matching name and scope, before release
[ ] Retention set to 14 months (or 360 max); any decrease confirmed by a human
[ ] Reporting identity chosen deliberately; User-ID hashed if used
[ ] Unwanted referrals and domains configured; internal/developer traffic filtered (filter in Testing first)
[ ] Only business-critical events marked as key events, within the cap, sign-off obtained
[ ] No PII in URLs or parameters; parameter allowlist in place in the tag manager
[ ] BigQuery and product links set, export cost stated
[ ] Verified in DebugView, Realtime, and standard reports (not Realtime alone)Audit prompt: "Here is the tracking plan and access to the GA4 property. Check each event maps to the least custom GA4 category that fits, every reported parameter is registered with matching scope, retention is 14 months, referral exclusions cover payment and auth domains, and no PII reaches URLs or parameters. List each gap and whether fixing it is retroactive."
Failure modes and anti-patterns
- Sending a parameter and never registering it. You spot it when a report shows "(not set)" or the dimension is missing from the list. Fix it by registering the dimension with a matching name and scope before release, and recover the pre-registration period from BigQuery if it was linked.
- Leaving retention at the default. You spot it when an exploration cannot go back a year. Fix it by setting 14 months (or the 360 maximum) at setup, because raising it later does not backfill. Never decrease retention without human sign-off, because the decrease deletes data.
- Personal data in URLs or event parameters. You spot it when an email or a name appears in
page_locationor a parameter. Fix it by stripping the data at the source and enforcing a parameter allowlist, and note that GA4 cannot remove a single parameter later; a deletion request wipes the whole value. - Duplicating an event GA4 already collects. You spot it when a metric reads roughly double, for example two
form_submitevents per submission. Fix it by choosing one source, automatic or manual, and disabling the other. - A high-cardinality custom dimension. You spot it when a dimension has thousands of values, accuracy warnings, or large "(other)" rows. Fix it by bucketing the values into ranges under 500 distinct per day and registering the bucketed value.
Quality bar for the setup
Before handing over, confirm every item:
- Every planned event is mapped to the least custom GA4 category that fits, recommended names are used where they exist, and names are within 40 characters with no reserved prefix.
- Every parameter that must appear in the interface is registered with a matching name and scope, before release.
- Retention is set deliberately to 14 months or the 360 maximum, and any decrease was confirmed by a human.
- No personal data reaches URLs or parameters, and a parameter allowlist is in place.
- Referral exclusions and domains are configured, and internal and developer traffic are filtered.
- Only business-critical events are marked as key events, within the current cap, with sign-off.
- BigQuery and product links are set, and the export cost was stated rather than assumed.
- The setup was verified in DebugView, Realtime and standard reports, not Realtime alone.
- Every version-dependent limit (custom dimensions, key events, parameters per event) was checked against current documentation.
Tool-specific appendix
GA4 specifics (verify version-dependent numbers before relying on them)
- Event categories: automatically collected, enhanced measurement, recommended, custom. Prefer the least
custom that fits; recommended names populate prebuilt reports.
- Hard rules: event names case-sensitive, 40-char limit; reserved prefixes ga_, google_, firebase_ and
reserved event names are not allowed; events must sit below the Google tag.
- Processing limits: up to 20 events per batch, 16 KB per send (an oversized batch is not processed),
events arriving more than 72 hours after they fired are ignored, key events are sent immediately.
- Custom dimensions/metrics: must be registered in the UI to appear in reports; not retroactive
("(not set)" before registration); standard-property slot limits are capped (verify current numbers);
prefix numeric-looking IDs with a letter; bucket dimensions above ~500 distinct values/day.
- Retention: 2 or 14 months (standard); 26/38/50 on 360; raising is applied to data not yet deleted,
lowering deletes older data at the next monthly run with a 24-hour revert window; affects explorations
and funnels, not standard aggregated reports.
- Identity: device-based is closest to the old model for sites without login; Google Signals adds
cross-device matching but applies modelling and data thresholds; User-ID needs a durable id, hashed if
derived from PII.
- BigQuery export: begins only when linked, is not retroactive, has a free tier then charges.Sources
- Google, GA4 events developer guide (the four event categories, recommended versus custom, events below the Google tag). Last verified 6 November 2026.
- Google, GA4 "about events" (batching of up to 20 events, 16 KB send limit, 72-hour arrival window, key events sent immediately, use existing events before custom). Last verified 6 November 2026.
- Google Analytics Help, data retention (2 and 14 month options, 360 options, retroactivity of raising versus lowering, 24-hour revert, reset on new activity, effect on explorations only). Last verified 6 November 2026.
- Louder, GA4 setup mistakes (retention default, PII in URLs and the GTM allowlist, custom dimension registration and the 25-dimension note, numeric-id prefixing, key events, referral exclusion and domain configuration, product linking, identity). Last verified 6 November 2026; dimension and key-event limits are version-dependent, so re-check the documentation.
- Search Engine Journal, GA4 mistakes (retention and reset-on-new-activity, high-cardinality dimensions above 500 values per day and bucketing, BigQuery linking and export sampling, reporting identity and modelling). Last verified 6 November 2026.
- Related skills: event-tracking-plan (the taxonomy this configures), gtm-container-management (deploying the tags and the parameter allowlist), consent-mode-tracking (consent configuration), analytics-qa-validation (proving it fires), conversion-tracking-capi (ad-platform conversions), funnel-analysis (analysis once the data is trusted).
On this page
- When to use this skill, and when not to
- Who it is for
- What is inside
- Example prompts
- Example output
- What the agent needs from you
- How to install and use it
- How to set up GA4 measurement step by step
- Worked example
- Situations this skill handles
- What makes this skill different
- Common mistakes
- Related skills
- Frequently asked questions
- Changelog
When to use this skill, and when not to
Use this skill to configure a new GA4 property, audit an existing one against its plan, or fix a specific setup fault: a dimension that will not show in reports, retention set too short, or self-referrals polluting attribution. It fires on GA4 property or data-stream setup, recommended versus custom events, custom dimensions, “(not set)”, data retention, key events, referral exclusions, Google Signals and BigQuery linking. Do not use it to design the taxonomy, deploy tags, configure consent, or analyse data already collected.
Who it is for
Analytics engineers, marketers, founders and anyone pointing an AI agent at a GA4 property they need to trust. You do not need to know every GA4 menu. You bring the tracking plan and access to the property, and the agent configures the event model, registers dimensions, sets retention and identity, and keeps personal data out, flagging the few settings that delete data before touching them.
What is inside
A six-step setup in a fixed order: confirm the plan and streams, map each event to the least custom GA4 category that fits, register custom dimensions before anything depends on them, set retention and identity on purpose, configure the data stream for attribution and privacy, then link products and verify. A worked example, a setup checklist, an event-mapping table, the five failure modes and a GA4 appendix come with it.
Example prompts
“Set up our new GA4 property from this tracking plan.” “Why does my custom dimension show (not set)?” “Audit our GA4 configuration before we trust the reports.” “Our payment redirect keeps starting new sessions, fix the attribution.”
Example output
The skill returns an event-to-model mapping, the custom dimensions to register with their scope, a retention and identity decision, the referral and domain settings, the key events to mark, and a verification pass in DebugView and standard reports. It flags destructive changes, such as decreasing retention, for confirmation first.
What the agent needs from you
The tracking plan, access to the GA4 property and its data streams, whether it is a standard or 360 property, the business-critical actions that should be key events, the domains that redirect users back, and whether a durable user identifier and BigQuery export are wanted. Without a plan there is no definition of correct, so the agent asks for it first.
How to install and use it
In the Claude apps, download the SKILL.md from this page, put it in a folder named ga4-measurement-setup, and upload that folder. In Claude Code, Codex and other Agent Skills tools, copy the folder into your skills directory. Then ask the agent to set up or audit your GA4 property and it loads the skill on its own.
How to set up GA4 measurement step by step
Install the skill as ga4-measurement-setup/SKILL.md. Give the agent the tracking plan and access to the property. It maps each event to the least custom GA4 category that fits, registers every reported parameter as a custom dimension with matching scope before release, sets event data retention to 14 months, chooses the reporting identity on purpose, excludes payment and auth domains as unwanted referrals, marks only business-critical key events, links BigQuery, then verifies in DebugView and standard reports. Confirm before it decreases retention or submits a deletion request.
Worked example
A SaaS site has a plan with sign_up, login, a custom trial_started event and a plan_tier property. The agent maps sign_up and login to the recommended names, keeps trial_started custom, and registers plan_tier before release so it does not read “(not set)”. It sets retention to 14 months, picks device-based identity, and excludes the Stripe and auth domains that had been splitting sessions. It marks sign_up and trial_started as key events, declines login, and links BigQuery with the cost stated. The two settings nobody would notice, the missing dimension and the missing referral exclusions, would each have quietly corrupted a core report.
Situations this skill handles
| Situation | What the skill does |
|---|---|
| New GA4 property from a plan | Maps events to the right category, registers dimensions, sets retention and identity |
| A dimension reading (not set) | Registers it in the UI with matching name and scope before release |
| Self-referrals from a payment page | Adds unwanted referrals and configures the domain list |
| History lost to short retention | Sets 14 months and warns that decreasing it deletes data |
| Personal data reaching GA4 | Strips it at source and enforces a parameter allowlist |
What makes this skill different
Most GA4 guides are either a list of mistakes or a scatter of official pages. This skill is a single ordered setup with decision rules and thresholds: 14-month retention, bucket a dimension above 500 distinct values a day, register before you rely on it, and never decrease retention without sign-off. Every figure is sourced or marked to verify against current documentation, and tag deployment, consent and QA are handed to their own skills.
Common mistakes
Sending a parameter and never registering it, so reports read “(not set)”. Leaving retention at the default and losing year-on-year history. Letting personal data reach URLs or parameters, which GA4 cannot later remove in isolation. Duplicating an event GA4 already collects, which doubles the count. Registering a high-cardinality dimension that degrades the reports it appears in.
Related skills
It configures the taxonomy from event-tracking-plan, deploys through gtm-container-management, and respects consent-mode-tracking. Prove it fires with analytics-qa-validation, send ad-platform conversions with conversion-tracking-capi, and analyse the data with funnel-analysis once it is trusted.
Frequently asked questions
How do I set up a GA4 property correctly?
Work in a fixed order: confirm the tracking plan and streams, map each event to the least custom GA4 category that fits, register every reported parameter as a custom dimension, set retention to 14 months, configure referral exclusions and identity, then link BigQuery and verify in DebugView and standard reports. Do the retention and dimension steps first, because neither is retroactive.
Why does my GA4 custom dimension show (not set)?
A parameter only appears in reports after you register it as a custom dimension in the GA4 interface, with a name and scope that match your tagging. Registration is not retroactive, so the period before you registered shows (not set). Register it before release, and recover earlier data from BigQuery if the property was linked.
What should GA4 data retention be set to?
Set event data retention to 14 months on a standard property, or the maximum on 360. The default is shorter and is not applied retroactively, so raise it at setup. Decreasing retention later deletes older data at the next monthly run with only a 24-hour window to revert, so treat any decrease as destructive.
Should I use recommended or custom events in GA4?
Use the least custom option that fits. If GA4 already collects the interaction automatically or through enhanced measurement, use that. If a recommended event name matches, use it exactly, because recommended names have predefined parameters and populate prebuilt reports. Create a custom event only when nothing else fits.
How do I stop payment or login domains showing as referrals?
Add every third party that redirects users back, such as payment processors, SSO providers and your own auth subdomains, to the unwanted referrals list, and add your domains to the domain configuration. Left out, they start new sessions and send conversions to a referral source instead of the original campaign.
How do I keep personal data out of GA4?
Strip personal data at the source and enforce a parameter allowlist in your tag manager so only approved parameters reach GA4. GA4 cannot exclude a single URL parameter and cannot later remove one parameter on its own; a deletion request wipes the whole value, so prevention at collection is the only reliable control.
Changelog
1.0.0, 6 November 2026: first release. Use, adapt and share this skill under CC BY 4.0: credit Afeez Adebayo and link to this page.
