@dreamdata_io/verify-tracking 0.1.0

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.
Files changed (108) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +756 -0
  3. package/dist/ai/checker.js +222 -0
  4. package/dist/ai/checker.js.map +1 -0
  5. package/dist/ai/checklist.js +190 -0
  6. package/dist/ai/checklist.js.map +1 -0
  7. package/dist/ai/cli-presets.js +27 -0
  8. package/dist/ai/cli-presets.js.map +1 -0
  9. package/dist/ai/evidence-view.js +143 -0
  10. package/dist/ai/evidence-view.js.map +1 -0
  11. package/dist/ai/local-cli.js +58 -0
  12. package/dist/ai/local-cli.js.map +1 -0
  13. package/dist/ai/openai-compatible.js +78 -0
  14. package/dist/ai/openai-compatible.js.map +1 -0
  15. package/dist/ai/response-parser.js +105 -0
  16. package/dist/ai/response-parser.js.map +1 -0
  17. package/dist/ai/types.js +2 -0
  18. package/dist/ai/types.js.map +1 -0
  19. package/dist/analysis/consent-mode.js +225 -0
  20. package/dist/analysis/consent-mode.js.map +1 -0
  21. package/dist/analysis/deployment.js +2658 -0
  22. package/dist/analysis/deployment.js.map +1 -0
  23. package/dist/analysis/diagnosis/copy.en.js +303 -0
  24. package/dist/analysis/diagnosis/copy.en.js.map +1 -0
  25. package/dist/analysis/diagnosis/diagnose.js +172 -0
  26. package/dist/analysis/diagnosis/diagnose.js.map +1 -0
  27. package/dist/analysis/diagnosis/docs.js +118 -0
  28. package/dist/analysis/diagnosis/docs.js.map +1 -0
  29. package/dist/analysis/diagnosis/index.js +5 -0
  30. package/dist/analysis/diagnosis/index.js.map +1 -0
  31. package/dist/analysis/diagnosis/rules.js +656 -0
  32. package/dist/analysis/diagnosis/rules.js.map +1 -0
  33. package/dist/analysis/diagnosis/types.js +2 -0
  34. package/dist/analysis/diagnosis/types.js.map +1 -0
  35. package/dist/cli.js +344 -0
  36. package/dist/cli.js.map +1 -0
  37. package/dist/config/env.js +100 -0
  38. package/dist/config/env.js.map +1 -0
  39. package/dist/config/preflight.js +167 -0
  40. package/dist/config/preflight.js.map +1 -0
  41. package/dist/config/user-config.js +79 -0
  42. package/dist/config/user-config.js.map +1 -0
  43. package/dist/evidence/collect.js +527 -0
  44. package/dist/evidence/collect.js.map +1 -0
  45. package/dist/evidence/consent-accept.js +377 -0
  46. package/dist/evidence/consent-accept.js.map +1 -0
  47. package/dist/evidence/consent.js +340 -0
  48. package/dist/evidence/consent.js.map +1 -0
  49. package/dist/evidence/constants.js +615 -0
  50. package/dist/evidence/constants.js.map +1 -0
  51. package/dist/evidence/globals.js +132 -0
  52. package/dist/evidence/globals.js.map +1 -0
  53. package/dist/evidence/gtm-container.js +432 -0
  54. package/dist/evidence/gtm-container.js.map +1 -0
  55. package/dist/evidence/heuristic-banner.js +107 -0
  56. package/dist/evidence/heuristic-banner.js.map +1 -0
  57. package/dist/evidence/http-probe.js +139 -0
  58. package/dist/evidence/http-probe.js.map +1 -0
  59. package/dist/evidence/init-script.js +112 -0
  60. package/dist/evidence/init-script.js.map +1 -0
  61. package/dist/evidence/network.js +365 -0
  62. package/dist/evidence/network.js.map +1 -0
  63. package/dist/evidence/preference-center.js +368 -0
  64. package/dist/evidence/preference-center.js.map +1 -0
  65. package/dist/evidence/script.js +425 -0
  66. package/dist/evidence/script.js.map +1 -0
  67. package/dist/evidence/second-page.js +332 -0
  68. package/dist/evidence/second-page.js.map +1 -0
  69. package/dist/evidence/selector-probe.js +53 -0
  70. package/dist/evidence/selector-probe.js.map +1 -0
  71. package/dist/evidence/stealth.js +21 -0
  72. package/dist/evidence/stealth.js.map +1 -0
  73. package/dist/evidence/types.js +14 -0
  74. package/dist/evidence/types.js.map +1 -0
  75. package/dist/interactive/prompt.js +31 -0
  76. package/dist/interactive/prompt.js.map +1 -0
  77. package/dist/mcp/server.js +308 -0
  78. package/dist/mcp/server.js.map +1 -0
  79. package/dist/mcp/summary.js +41 -0
  80. package/dist/mcp/summary.js.map +1 -0
  81. package/dist/report/context.js +184 -0
  82. package/dist/report/context.js.map +1 -0
  83. package/dist/report/projection.js +125 -0
  84. package/dist/report/projection.js.map +1 -0
  85. package/dist/report/quote-check.js +90 -0
  86. package/dist/report/quote-check.js.map +1 -0
  87. package/dist/report/render.js +178 -0
  88. package/dist/report/render.js.map +1 -0
  89. package/dist/report/serializers.js +124 -0
  90. package/dist/report/serializers.js.map +1 -0
  91. package/dist/report/store.js +139 -0
  92. package/dist/report/store.js.map +1 -0
  93. package/dist/run/verify.js +77 -0
  94. package/dist/run/verify.js.map +1 -0
  95. package/dist/utils/duration.js +10 -0
  96. package/dist/utils/duration.js.map +1 -0
  97. package/dist/utils/errors.js +17 -0
  98. package/dist/utils/errors.js.map +1 -0
  99. package/dist/utils/logger.js +59 -0
  100. package/dist/utils/logger.js.map +1 -0
  101. package/dist/utils/runTimingsLog.js +27 -0
  102. package/dist/utils/runTimingsLog.js.map +1 -0
  103. package/dist/utils/slug.js +27 -0
  104. package/dist/utils/slug.js.map +1 -0
  105. package/dist/version.js +10 -0
  106. package/dist/version.js.map +1 -0
  107. package/package.json +57 -0
  108. package/scripts/install.sh +314 -0
@@ -0,0 +1,365 @@
1
+ import { COOKIELESS_LIBRARY_NAME_MARKER, DEFAULT_TRACKING_HOSTS, ENDPOINT_NAMES, ENDPOINT_REGEX, isDreamdataUrl, THIRD_PARTY_SEGMENT_TRACKING_HOST, } from "./constants.js";
2
+ function classifyEndpoint(url) {
3
+ const match = ENDPOINT_REGEX.exec(url);
4
+ if (!match)
5
+ return {};
6
+ const endpoint = match[1];
7
+ return { endpoint, endpointName: ENDPOINT_NAMES[endpoint] };
8
+ }
9
+ function safePostDataJSON(request) {
10
+ try {
11
+ return request.postDataJSON();
12
+ }
13
+ catch {
14
+ return undefined;
15
+ }
16
+ }
17
+ function asBag(value) {
18
+ return value !== null && typeof value === "object" && !Array.isArray(value) ? value : undefined;
19
+ }
20
+ /**
21
+ * A `/api/v1/b` batch wraps N events under `batch`. Flatten so identity and
22
+ * library checks look at the events themselves, not just the envelope.
23
+ */
24
+ function eventsOf(payload) {
25
+ const root = asBag(payload);
26
+ if (!root)
27
+ return [];
28
+ const batch = Array.isArray(root.batch) ? root.batch : [];
29
+ const nested = batch.map(asBag).filter((e) => e !== undefined);
30
+ return [root, ...nested];
31
+ }
32
+ function libraryNameOf(event) {
33
+ const name = asBag(asBag(event.context)?.library)?.name;
34
+ return typeof name === "string" ? name : undefined;
35
+ }
36
+ export function classifyMode(payload) {
37
+ const names = eventsOf(payload).map(libraryNameOf).filter((n) => n !== undefined);
38
+ if (names.length === 0)
39
+ return "unknown";
40
+ return names.some((n) => n.toLowerCase().includes(COOKIELESS_LIBRARY_NAME_MARKER)) ? "cookieless" : "normal";
41
+ }
42
+ function isPresent(value) {
43
+ if (value === undefined || value === null)
44
+ return false;
45
+ if (typeof value === "string")
46
+ return value.length > 0;
47
+ if (typeof value === "object")
48
+ return Object.keys(value).length > 0;
49
+ return true;
50
+ }
51
+ /**
52
+ * Deterministic presence check for the identity fields the checklist asks
53
+ * about. Cookieless events legitimately carry no anonymousId, so recording
54
+ * this per-request lets the judge apply the right rule per mode instead of
55
+ * inferring absence from a raw payload dump.
56
+ */
57
+ export function extractWriteKeys(payload) {
58
+ const keys = eventsOf(payload)
59
+ .map((event) => event.writeKey)
60
+ .filter((key) => typeof key === "string" && key.length > 0);
61
+ return [...new Set(keys)];
62
+ }
63
+ /**
64
+ * The event's own id, as the envelope carries it. Two requests sharing one means
65
+ * the SAME event was delivered twice, which no single healthy instance does —
66
+ * the cheapest sign of a second bundle replaying a buffer the first already
67
+ * sent. A batch envelope has no id of its own, hence the null.
68
+ */
69
+ export function extractMessageId(payload) {
70
+ const id = asBag(payload)?.messageId;
71
+ return typeof id === "string" && id.length > 0 ? id : null;
72
+ }
73
+ export function extractIdentity(payload) {
74
+ const events = eventsOf(payload);
75
+ const anyOf = (read) => events.some((event) => isPresent(read(event)));
76
+ return {
77
+ hasWriteKey: anyOf((e) => e.writeKey),
78
+ hasAnonymousId: anyOf((e) => e.anonymousId ?? asBag(e.context)?.anonymousId),
79
+ hasUserId: anyOf((e) => e.userId ?? asBag(e.context)?.userId),
80
+ hasUserData: anyOf((e) => e.userData ?? asBag(e.context)?.userData ?? asBag(e.context)?.user_data),
81
+ };
82
+ }
83
+ /**
84
+ * Attaches a passive request listener (no interception) for event requests.
85
+ *
86
+ * Dreamdata-owned hosts are recognised automatically, so a first-party install
87
+ * on api.s.dreamdata.io needs no configuration. `trackingHosts` extends that
88
+ * for fully custom CNAMEs, which cannot be inferred; the watched set is
89
+ * recorded in the report because anything outside it is invisible to the run.
90
+ */
91
+ export function attachNetworkCollector(page, trackingHosts = DEFAULT_TRACKING_HOSTS) {
92
+ const requests = [];
93
+ let unattributedRequests = [];
94
+ let installWriteKey = null;
95
+ const isTracked = (url) => isDreamdataUrl(url, trackingHosts);
96
+ const isOurs = (request) => installWriteKey !== null && extractWriteKeys(request.payload).includes(installWriteKey);
97
+ page.on("request", (request) => {
98
+ const url = request.url();
99
+ const { endpoint, endpointName } = classifyEndpoint(url);
100
+ // Dreamdata's hosts also serve the bundles themselves and helper scripts.
101
+ // Only event requests belong in the request log; a script download counted
102
+ // as an event would read as tracking that never happened.
103
+ if (endpoint === undefined)
104
+ return;
105
+ const payload = request.method() === "POST" ? safePostDataJSON(request) : undefined;
106
+ const watched = isTracked(url);
107
+ if (!watched && !isRequestCandidate(url, payload))
108
+ return;
109
+ const entry = {
110
+ url,
111
+ method: request.method(),
112
+ timestamp: Date.now(),
113
+ endpoint,
114
+ endpointName,
115
+ payload,
116
+ mode: classifyMode(payload),
117
+ identity: extractIdentity(payload),
118
+ };
119
+ if (watched || isOurs(entry))
120
+ requests.push(entry);
121
+ else
122
+ unattributedRequests.push(entry);
123
+ });
124
+ page.on("requestfinished", async (request) => {
125
+ const url = request.url();
126
+ const response = await request.response().catch(() => null);
127
+ if (!response)
128
+ return;
129
+ // Looked up after the await, because the request may have been promoted
130
+ // out of one log and into the other while the response was in flight.
131
+ const match = requests.find((r) => r.url === url && r.status === undefined) ??
132
+ unattributedRequests.find((r) => r.url === url && r.status === undefined);
133
+ if (match)
134
+ match.status = response.status();
135
+ });
136
+ return {
137
+ requests,
138
+ get unattributedRequests() {
139
+ return unattributedRequests;
140
+ },
141
+ attributeTo: (writeKey) => {
142
+ installWriteKey = writeKey;
143
+ if (writeKey === null)
144
+ return;
145
+ const promoted = unattributedRequests.filter(isOurs);
146
+ if (promoted.length === 0)
147
+ return;
148
+ unattributedRequests = unattributedRequests.filter((b) => !isOurs(b));
149
+ requests.push(...promoted);
150
+ // Order is evidence here: determineCookielessSeenFirst reads which mode
151
+ // fired first, and the second-page probe slices this log by position.
152
+ requests.sort((a, b) => a.timestamp - b.timestamp);
153
+ },
154
+ };
155
+ }
156
+ /**
157
+ * A request on a host this run has no reason to watch, that still looks like
158
+ * one of ours.
159
+ *
160
+ * respond.io delivers its events to dd.respond.io — a first-party CNAME onto
161
+ * Dreamdata — and the run reported "no request reached Dreamdata in any phase"
162
+ * about a site whose every page view was being delivered and accepted. The
163
+ * host cannot be inferred, and requiring --tracking-host means the default
164
+ * answer for a custom-domain install is a confident false negative.
165
+ *
166
+ * This is deliberately only a CANDIDATE. The shape it matches is Segment's
167
+ * analytics.js envelope, which is what Dreamdata's Segment-compatible bundle
168
+ * sends AND what a self-hosted Segment proxy on events.customer.com sends.
169
+ * Nothing here decides the request is Dreamdata's; the writeKey does that,
170
+ * against the key the installed bundle carries (see attributeTo).
171
+ * api.segment.io is excluded outright — real Segment already has its own
172
+ * evidence path (thirdPartySegmentSignals) and must not be reachable
173
+ * through this one.
174
+ */
175
+ function isRequestCandidate(url, payload) {
176
+ if (extractWriteKeys(payload).length === 0)
177
+ return false;
178
+ try {
179
+ return new URL(url).hostname.toLowerCase() !== THIRD_PARTY_SEGMENT_TRACKING_HOST;
180
+ }
181
+ catch {
182
+ return false;
183
+ }
184
+ }
185
+ /**
186
+ * A passive counter for requests this phase sent to Segment's own collection
187
+ * endpoint (api.segment.io) — the client-side half of a real Segment install.
188
+ *
189
+ * Deliberately not folded into `attachNetworkCollector`: that function parses
190
+ * every Dreamdata request's payload for endpoint/mode/identity, none of which
191
+ * applies here. All this needs to answer is "did the site talk to Segment at
192
+ * all", so it stays a bare counter rather than a second copy of the request
193
+ * log.
194
+ */
195
+ export function attachThirdPartySegmentCollector(page) {
196
+ let count = 0;
197
+ page.on("request", (request) => {
198
+ try {
199
+ if (new URL(request.url()).hostname.toLowerCase() === THIRD_PARTY_SEGMENT_TRACKING_HOST)
200
+ count += 1;
201
+ }
202
+ catch {
203
+ // Not a parseable URL, so not a match either.
204
+ }
205
+ });
206
+ return { count: () => count };
207
+ }
208
+ export function summarizeDreamdataRequestCounts(requests) {
209
+ const counts = {};
210
+ for (const req of requests) {
211
+ const key = req.endpointName ?? "unknown";
212
+ counts[key] = (counts[key] ?? 0) + 1;
213
+ }
214
+ return counts;
215
+ }
216
+ export function summarizeModeCounts(requests) {
217
+ return {
218
+ cookielessRequestCount: requests.filter((r) => r.mode === "cookieless").length,
219
+ normalRequestCount: requests.filter((r) => r.mode === "normal").length,
220
+ };
221
+ }
222
+ /** Every distinct writeKey actually seen on the wire, in first-seen order. */
223
+ export function summarizeObservedWriteKeys(requests) {
224
+ return [...new Set(requests.flatMap((r) => extractWriteKeys(r.payload)))];
225
+ }
226
+ /**
227
+ * The analytics builds an event names in its own `context.library`.
228
+ *
229
+ * One running copy of the script stamps one build string on every event it
230
+ * sends, however many that is and whichever page view they belong to. So a
231
+ * second string is a second copy running — the one duplicate-install signal
232
+ * that no timing artefact can imitate, because two loads of one page, a
233
+ * queued request delivered late and a retried delivery all still come from
234
+ * the same build.
235
+ */
236
+ export function extractLibraries(payload) {
237
+ const builds = eventsOf(payload)
238
+ .map((event) => asBag(asBag(event.context)?.library))
239
+ .filter((library) => library !== undefined)
240
+ .map((library) => ({
241
+ name: typeof library.name === "string" ? library.name : "unknown",
242
+ version: typeof library.version === "string" ? library.version : "unknown",
243
+ }));
244
+ return [...new Map(builds.map((build) => [formatLibraryBuild(build), build])).values()];
245
+ }
246
+ /** `name@version`, the form used everywhere a build is reported to a human. */
247
+ export function formatLibraryBuild({ name, version }) {
248
+ return `${name}@${version}`;
249
+ }
250
+ /**
251
+ * Every distinct build seen on the wire, in first-seen order.
252
+ *
253
+ * Recorded because it is invisible in the counts: two copies of the script
254
+ * double every page view while each individual request still looks correct.
255
+ */
256
+ export function summarizeObservedLibraries(requests) {
257
+ return [...new Set(requests.flatMap((r) => extractLibraries(r.payload).map(formatLibraryBuild)))];
258
+ }
259
+ /**
260
+ * true = cookieless fired first, false = normal fired first, null = one or
261
+ * both modes never produced a request (not enough evidence either way).
262
+ *
263
+ * Descriptive only — kept in the JSON report for a human reading a timeline,
264
+ * and deliberately not shown to the model. The cookieless snippet stands down
265
+ * when it finds the normal tag present and unblocked, and the normal bundle
266
+ * deletes the cookieless global once it initializes, so the two are meant to
267
+ * be mutually exclusive rather than ordered. Whether BOTH fired in one phase
268
+ * is the finding; which came first is a race with no correct answer.
269
+ */
270
+ export function determineCookielessSeenFirst(requests) {
271
+ const firstCookieless = requests.find((r) => r.mode === "cookieless")?.timestamp;
272
+ const firstNormal = requests.find((r) => r.mode === "normal")?.timestamp;
273
+ if (firstCookieless === undefined || firstNormal === undefined)
274
+ return null;
275
+ return firstCookieless <= firstNormal;
276
+ }
277
+ function parseEventTime(value) {
278
+ if (typeof value === "number" && Number.isFinite(value))
279
+ return value;
280
+ if (typeof value === "string") {
281
+ const parsed = Date.parse(value);
282
+ return Number.isNaN(parsed) ? null : parsed;
283
+ }
284
+ return null;
285
+ }
286
+ /**
287
+ * When the BROWSER created this event, from the payload's own `timestamp`,
288
+ * as opposed to when it reached the wire.
289
+ *
290
+ * The two are usually milliseconds apart and the distinction never matters —
291
+ * until a navigation happens in between. Earliest wins for a batch: the
292
+ * envelope belongs to the page that produced its oldest event.
293
+ */
294
+ export function eventCreatedAt(payload) {
295
+ const times = eventsOf(payload)
296
+ .map((event) => parseEventTime(event.timestamp))
297
+ .filter((ms) => ms !== null);
298
+ return times.length === 0 ? null : Math.min(...times);
299
+ }
300
+ /**
301
+ * Splits a request log at a navigation by which page view each event was
302
+ * CREATED on, not which one it happened to be delivered during.
303
+ *
304
+ * A request can still be sitting in the bundle's queue when a navigation
305
+ * starts and only reach the network afterwards. Attributing it by delivery
306
+ * time counts it against the page it landed on, which reads as that page view
307
+ * being tracked twice with no second loader anywhere to explain it — and, on
308
+ * a second-page probe, as the first page's tracking having "survived" a
309
+ * navigation it never actually made.
310
+ *
311
+ * An event with no readable creation time stays with the page it arrived on:
312
+ * dropping on an unknown would invent silence that was never observed.
313
+ *
314
+ * Not a complete separation, and cannot be: the bundle stamps `timestamp` when
315
+ * it DISPATCHES an event, not when page() was called, so an event that page()
316
+ * queued before a navigation carries a stamp taken after it — observed on
317
+ * maxio.com, where the request the accept click produced was stamped mid-reload
318
+ * and so reads as the reloaded page's own. Anything that must not be fooled by
319
+ * that has to be structural instead; page-view-counted-once is, by leaving the
320
+ * banner-answering entry page unjudged.
321
+ */
322
+ /**
323
+ * Splits the requests seen since the second-page walk began into the three
324
+ * things they can be.
325
+ *
326
+ * The walk is no longer one navigation. A candidate that lands on an
327
+ * uninstrumented sub-site is left behind by going BACK to the first page, and
328
+ * that return load fires a page view of its own — a request belonging to
329
+ * neither page, which credited to either one would invent a duplicate page
330
+ * view on the first page or fake tracking on the second.
331
+ *
332
+ * `carriedOver` keeps its old meaning: created before the walk started at
333
+ * all, so it belongs to the first page whenever it was finally delivered.
334
+ * `discarded` is everything the retries produced in between. With no retries
335
+ * `acceptedAt` equals `walkStartedAt`, nothing is discarded, and this is the
336
+ * same split as before.
337
+ */
338
+ export function partitionSecondPageRequests(requests, walkStartedAt, acceptedAt) {
339
+ const fired = [];
340
+ const carriedOver = [];
341
+ const discarded = [];
342
+ for (const request of requests) {
343
+ const createdAt = eventCreatedAt(request.payload) ?? request.timestamp;
344
+ if (createdAt < walkStartedAt)
345
+ carriedOver.push(request);
346
+ else if (createdAt < acceptedAt)
347
+ discarded.push(request);
348
+ else
349
+ fired.push(request);
350
+ }
351
+ return { fired, carriedOver, discarded };
352
+ }
353
+ export function partitionCarriedOverRequests(requests, navigationStartedAt) {
354
+ const fired = [];
355
+ const carriedOver = [];
356
+ for (const request of requests) {
357
+ const createdAt = eventCreatedAt(request.payload);
358
+ if (createdAt !== null && createdAt < navigationStartedAt)
359
+ carriedOver.push(request);
360
+ else
361
+ fired.push(request);
362
+ }
363
+ return { fired, carriedOver };
364
+ }
365
+ //# sourceMappingURL=network.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"network.js","sourceRoot":"","sources":["../../src/evidence/network.ts"],"names":[],"mappings":"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"}