DataLayer Analytics — Playwright
datalayer-analytics-playwright
Automated window.dataLayer analytics validation for GTM/GA4. Creates test suites from tracking specs or discovers events from live pages using Playwright codegen and dataLayer capture. Supports standard Playwright and BDD modes. Use when creating, running, capturing, or debugging GTM/GA4 tracking...
SKILL.md
Full skill instructions
DataLayer Analytics — Playwright
Automated window.dataLayer event validation using Playwright. Creates, runs, and maintains analytics tracking tests so you never ship broken tracking again.
When to Use
- Validate GTM / GA4 events fire correctly with the right payloads
- Create analytics regression tests from a tracking spec (Confluence, Notion, or manual)
- Discover what events a page actually fires (no spec needed)
- Debug mismatches between expected and actual dataLayer payloads
- Maintain test data as tracking implementations evolve
Two Test Modes
Auto-detected based on your project setup:
| Mode | Files per Component | Detection |
|---|---|---|
| Standard Playwright | 3 (JSON + spec + page object) | Default |
| BDD (playwright-bdd) | 4 (JSON + feature + steps + page object) | playwright-bdd in package.json or .feature files present |
Both modes share the same JSON format, page objects, and DataLayer utilities.
Supported Events
| Event | Fires When |
|---|---|
element_visibility | Component scrolls into view |
cta_click | User clicks a CTA / button / link |
form_interaction | User interacts with form fields |
form_submit | Form is submitted |
generate_lead | Lead generation conversion (GA4) |
select_content | User selects content (GA4) |
add_to_cart | Item added to cart (GA4 ecommerce) |
purchase | Transaction completed (GA4 ecommerce) |
| Any custom event | Your tracking fires it |
What You Can Say to Your Agent
"Create dataLayer tests for the hero component using this Confluence spec: https://wiki.example.com/pages/12345"
"Create analytics tests for the newsletter signup — no spec, discover the events from the live page"
"Discover the events for the nav menu by recording my clicks with codegen, then capture the payloads"
"Create dataLayer tests for the checkout button. It fires cta_click with click_text='Buy Now', click_url='/checkout', component_name='Checkout CTA'"
"Run the analytics tests for the button component and show me what's different"
"The cta_click changes look correct — update the JSON with those actuals"
"Don't update — the actual looks wrong, this might be a tracking bug"
"Add an element_visibility event to the button component tests"
"The button test is failing because the locator changed — inspect the live DOM and update the page object"
"Show me everything in the dataLayer on the checkout page"
Workflow Modes
| Mode | When | What Happens |
|---|---|---|
| Full | "Create tests for X using this spec" | Create files → run → extract → compare → wait for approval → update → verify |
| Discovery | "Create tests for X — no spec" | Infer events → skeleton JSON → run → extract → compare → wait → fill |
| Deferred | "Create test files for X — don't run" | Create files from spec only. Execute later. |
| Debug | "Run the tests for X and show me diffs" | Run → extract → compare. No update unless asked. |
Assertion Strategy
| Assertion | BDD Step | Clears? | Context |
|---|---|---|---|
| First-match + clear | contain expected "{key}" event | Yes | Storybook (isolated components) |
| Component-aware match | contain a matching "{key}" event | No | App tests (multi-component pages) |
| Component-aware + clear | contain a matching "{key}" event and clear | Yes | App interaction events |
Storybook: Default to first-match + clear. App tests: Always use findMatchingDataLayerEvent — extracts event + parameters.content.name from expected JSON to locate the correct component's event, then toMatchObject provides field diffs. See references/assertion-strategy.md for details.
Critical Rules
- Capture ALL properties from actual events. Only exclude
gtm.uniqueEventId. - Never remove properties to fix flaky tests. Make dynamic values deterministic via URL args.
- Never modify
analytics-common-step.ts,analytics-logger.ts, oranalytics-helpers.ts. New utility methods may be added todatalayer-util.tsbut existing methods must not be altered. - Use
toMatchObject()for assertions.toEqual()is banned. - Never auto-update JSON — always present comparison and wait for user approval.
- Only fetch tracking specs from URLs explicitly provided by the user. Always display extracted event names for user approval before creating files.
- One attempt per fix. After a failed run, apply one fix and re-run once. If it still fails, stop and report what was tried, the exact error, and the likely cause — never loop.
- Accept the consent banner before capture ONLY if the page gates tracking behind it. No consent gate → skip it; don't add banner handling pre-emptively. The accept selector is project-specific — ask the user.
References
For detailed implementation instructions, read these in order:
references/workflow.md— Full step-by-step: setup, spec extraction, file creation, execution, extraction, comparisonreferences/discovery-and-capture.md— Codegen for interactions +window.dataLayerdump for payloads, conditional consent gating, tracking pre-flightreferences/locator-rules.md— Hybrid locator model (CSS default, role-based fallback), container-level ambiguity, CTA navigation preventionreferences/assertion-strategy.md— First-match vs deep-partial-match with examplesreferences/event-patterns.md— Standard dataLayer event structures and parametersreferences/extraction-workflow.md— Token-efficient extraction and comparison pattern
Requirements
- Node.js 18+
- Playwright
- allure-js-commons + allure-playwright
- playwright-bdd (BDD mode only)
