@escape-game-over/atlas 0.1.66 → 0.1.67
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/checks.md +8 -1
- package/docs/client-scripts.md +82 -0
- package/package.json +1 -1
package/docs/checks.md
CHANGED
|
@@ -89,6 +89,13 @@ augmentation is real. Both examples carry one:
|
|
|
89
89
|
two files in it, and [`b2b`](../examples/b2b/type-tests/wiring.ts) against one
|
|
90
90
|
with none, where the union is empty and *every* path is rejected.
|
|
91
91
|
|
|
92
|
+
Declared analytics events are the other augmentation, and the opposite case:
|
|
93
|
+
nothing is inferred, so a declaration means the same thing here as in a project.
|
|
94
|
+
`type-tests/declared-events.ts` writes one by the package's own name, as a
|
|
95
|
+
project does, and asserts that an undeclared name, missing required data and
|
|
96
|
+
data on an event declared without any all fail. The declaration holds for the
|
|
97
|
+
whole program, so the runtime tests call the names it declares.
|
|
98
|
+
|
|
92
99
|
## Runtime tests
|
|
93
100
|
|
|
94
101
|
```bash
|
|
@@ -117,7 +124,7 @@ dependencies at all. Vitest type-checks them itself when it runs them.
|
|
|
117
124
|
| `breadcrumbs.test.ts` | the trail, a dropped ancestor, `orphanSegments`, and how a gap is reported |
|
|
118
125
|
| `jsonld/*.test.ts` | that a `</script>` in any value cannot close the block, each node's shape and `@id`, and how a price table becomes offers |
|
|
119
126
|
| `analytics.test.ts` | Umami's attributes, its three-state booleans, the `domains` list that would record nothing, and that `consentRequired` answers exactly when a tag was emitted |
|
|
120
|
-
| `google-analytics.test.ts` | that consent is denied first and precedes every tag, one loader for many ids, dead `UA-` properties,
|
|
127
|
+
| `google-analytics.test.ts` | that consent is denied first and precedes every tag, one loader for many ids, dead `UA-` properties, the preconnect — once, ahead of the block that writes the loader's URL, never `crossorigin` — and where `googleEvent` sends, per setting |
|
|
121
128
|
| `contact.test.ts` | the E.164 a `tel:` needs — trunk zero dropped, spacing stripped — and the displayed form kept |
|
|
122
129
|
| `hours.test.ts` | collapsing a week into runs, week start changing the answer, and every impossible week that throws |
|
|
123
130
|
| `money.test.ts` | a bare count widened to a band, the span of a table, and the gaps and overlaps that throw |
|
package/docs/client-scripts.md
CHANGED
|
@@ -535,6 +535,88 @@ move before this pauses them. Left in, everything still works. `muted` is also
|
|
|
535
535
|
set on attach, since no browser will start an unmuted video nobody pressed play
|
|
536
536
|
on.
|
|
537
537
|
|
|
538
|
+
## Events
|
|
539
|
+
|
|
540
|
+
One function per vendor, all dropped silently where the vendor is not
|
|
541
|
+
configured, not loaded or not permitted — an analytics call must never be the
|
|
542
|
+
reason a page misbehaves.
|
|
543
|
+
|
|
544
|
+
| Function | Names | Consent |
|
|
545
|
+
| -------------- | ------------------------------ | ------------------------------------------ |
|
|
546
|
+
| `googleEvent` | GA4's recommended, or declared | Consent Mode, which Google already applies |
|
|
547
|
+
| `metaEvent` | Meta's standard, or declared | the pixel loads only once granted |
|
|
548
|
+
| `tiktokEvent` | TikTok's standard, or declared | the pixel loads only once granted |
|
|
549
|
+
| `snapEvent` | Snap's standard only | checked on every call |
|
|
550
|
+
| `axonEvent` | Axon's standard only | checked on every call |
|
|
551
|
+
| `umamiEvent` | declared only | none needed: Umami sets no cookie |
|
|
552
|
+
| `dripEvent` | declared only | checked on every call |
|
|
553
|
+
| `clarityEvent` | declared only | none needed: cookieless until granted |
|
|
554
|
+
|
|
555
|
+
**A project declares its own events once**, for every site it builds, by
|
|
556
|
+
merging into the interface each function reads — the arrangement
|
|
557
|
+
`PublicFileRegistry` uses. Each name maps to the data it carries, `undefined` for
|
|
558
|
+
none:
|
|
559
|
+
|
|
560
|
+
```ts
|
|
561
|
+
// src/events.ts — any file the project's tsconfig includes
|
|
562
|
+
export {};
|
|
563
|
+
|
|
564
|
+
declare module "@escape-game-over/atlas/client" {
|
|
565
|
+
interface GoogleCustomEvents {
|
|
566
|
+
form_submission_contact: undefined;
|
|
567
|
+
form_submission_quote: { readonly room: string };
|
|
568
|
+
}
|
|
569
|
+
interface UmamiEvents {
|
|
570
|
+
"franchise-enquiry": { readonly country: string };
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
```
|
|
574
|
+
|
|
575
|
+
```ts
|
|
576
|
+
googleEvent("form_submission_contact");
|
|
577
|
+
googleEvent("form_submission_quote", { room: "Tomb" });
|
|
578
|
+
googleEvent("form_submissions_contact"); // does not compile
|
|
579
|
+
```
|
|
580
|
+
|
|
581
|
+
A name nobody declared does not compile, so a typo cannot quietly become a
|
|
582
|
+
second event in a report — which is why this is not a `string` with the standard
|
|
583
|
+
names offered for autocomplete. Data declared with a required field is required
|
|
584
|
+
at every call. The interfaces are `GoogleCustomEvents`, `MetaCustomEvents`,
|
|
585
|
+
`TikTokCustomEvents`, `UmamiEvents`, `DripEvents` and `ClarityEvents`; Clarity
|
|
586
|
+
carries a name only, so its entries are all `undefined`. Snap and Axon take no
|
|
587
|
+
declarations because they accept no names but their own.
|
|
588
|
+
|
|
589
|
+
**The file must be a module** — the `export {}` above. Without an import or an
|
|
590
|
+
export, `declare module` *replaces* the package's types instead of adding to
|
|
591
|
+
them, and every import from it breaks.
|
|
592
|
+
|
|
593
|
+
**Declared data is sent as written, so it names what the visitor chose, never
|
|
594
|
+
who they are.** Google's terms forbid sending it anything that identifies a
|
|
595
|
+
person — a name, an email, a phone number, a free-text message — and its
|
|
596
|
+
[guidance](https://support.google.com/analytics/answer/6366371) names event
|
|
597
|
+
parameters as the usual leak. The standard parameter types have no field for
|
|
598
|
+
any of those; a declaration is where one would have to be added, deliberately.
|
|
599
|
+
|
|
600
|
+
### `googleEvent`: where it goes
|
|
601
|
+
|
|
602
|
+
The deployment's `google` settings decide, not the caller. The head script
|
|
603
|
+
defines a global — `GOOGLE_EVENT_GLOBAL`, beside `CONSENT_UPDATE_GLOBAL` and for
|
|
604
|
+
the same reason — that sends:
|
|
605
|
+
|
|
606
|
+
- with `tagIds`: `gtag("event", name, data)`, which `gtag.js` reads;
|
|
607
|
+
- with `containerIds`: `dataLayer.push({ event: name, ...data })`, which is what
|
|
608
|
+
a Tag Manager *Custom Event* trigger listens for — the `dataLayer.push` a
|
|
609
|
+
marketing agency's brief asks for;
|
|
610
|
+
- with both, both. A container that also runs a GA4 tag on the same event then
|
|
611
|
+
counts it twice; that is set up in Tag Manager, where lib cannot see it.
|
|
612
|
+
|
|
613
|
+
The ecommerce events — `purchase`, `add_to_cart`, `view_item` and the rest — go
|
|
614
|
+
to Tag Manager under an `ecommerce` key, after a `{ ecommerce: null }` that
|
|
615
|
+
clears the previous one, which is the shape its GA4 tags read items and revenue
|
|
616
|
+
from. `purchase` does not compile without `value`, `currency` and
|
|
617
|
+
`transaction_id`: without them GA records a sale of nothing, and a reload
|
|
618
|
+
records it again.
|
|
619
|
+
|
|
538
620
|
## Testing
|
|
539
621
|
|
|
540
622
|
None of these tests has a document, and none needs one: every module under test
|