Fix GA4 measurement health for sparse API responses (#512)

This commit is contained in:
Ben Senescu 2026-08-20 17:22:30 -04:00 committed by Ben Senescu
parent b9c1b0255a
commit 47883b5d5a
3 changed files with 16 additions and 18 deletions

View File

@ -10,6 +10,7 @@ data, or sensitive paths.
## Open ## Open
- [ ] `2026-08-20T20:36:32Z``codex` — The PR preview Access check treats an immediate workers.dev 404 as proof the preview is public, even though the same URL can begin returning the expected Access redirect seconds later; retry 404 responses as propagation-era errors before failing and recommending stage destruction.
- [ ] `2026-08-18T03:06:44Z``claude` — Changing an MCP tool's `outputSchema` while the dev server hot-reloads makes in-flight MCP sessions reject the tool's own (already billed) results — clients validate against the schema cached at connect time, surfacing as "must NOT have additional properties". Note in the MCP dev docs/skill: reconnect the MCP session after any output-schema change before re-testing live. - [ ] `2026-08-18T03:06:44Z``claude` — Changing an MCP tool's `outputSchema` while the dev server hot-reloads makes in-flight MCP sessions reject the tool's own (already billed) results — clients validate against the schema cached at connect time, surfacing as "must NOT have additional properties". Note in the MCP dev docs/skill: reconnect the MCP session after any output-schema change before re-testing live.
- [ ] `2026-08-05T20:59:09Z``codex` — The documented `pnpm seed:rank-tracking` command fails before opening local D1 because `scripts/seed-rank-tracking.ts` imports the provider-aware `src/db/schema` barrel and plain `tsx` cannot load the resulting `cloudflare:workers` URL. Keep the seed script on dialect-local schema imports or run it through a Workers-compatible execution path. (Workaround: seed via raw SQL with `wrangler d1 execute DB --local`.) - [ ] `2026-08-05T20:59:09Z``codex` — The documented `pnpm seed:rank-tracking` command fails before opening local D1 because `scripts/seed-rank-tracking.ts` imports the provider-aware `src/db/schema` barrel and plain `tsx` cannot load the resulting `cloudflare:workers` URL. Keep the seed script on dialect-local schema imports or run it through a Workers-compatible execution path. (Workaround: seed via raw SQL with `wrangler d1 execute DB --local`.)
- [ ] `2026-08-01T16:28:36Z``claude` — web's pinned wrangler 4.71.0 fails `kv namespace create` with a bare "Authentication error [code: 10000]" even though the OAuth token has workers_kv write scope; wrangler@4.118.0 succeeds with identical auth. Fix: bump wrangler in web/package.json. - [ ] `2026-08-01T16:28:36Z``claude` — web's pinned wrangler 4.71.0 fails `kv namespace create` with a bare "Authentication error [code: 10000]" even though the OAuth token has workers_kv write scope; wrangler@4.118.0 succeeds with identical auth. Fix: bump wrangler in web/package.json.

View File

@ -164,14 +164,6 @@ describe("ga4Client admin API", () => {
.mockResolvedValueOnce( .mockResolvedValueOnce(
jsonResponse({ jsonResponse({
streamEnabled: true, streamEnabled: true,
scrollsEnabled: true,
outboundClicksEnabled: true,
siteSearchEnabled: true,
videoEngagementEnabled: true,
fileDownloadsEnabled: true,
pageChangesEnabled: true,
formInteractionsEnabled: false,
searchQueryParameter: "q,s",
}), }),
) )
.mockResolvedValueOnce( .mockResolvedValueOnce(
@ -222,7 +214,11 @@ describe("ga4Client admin API", () => {
const metrics = await client.listCustomMetrics("properties/11"); const metrics = await client.listCustomMetrics("properties/11");
expect(streams[0]?.webStreamData?.measurementId).toBe("G-ABC123"); expect(streams[0]?.webStreamData?.measurementId).toBe("G-ABC123");
expect(enhanced.siteSearchEnabled).toBe(true); expect(enhanced).toMatchObject({
streamEnabled: true,
siteSearchEnabled: false,
searchQueryParameter: "",
});
expect(keyEvents[0]?.eventName).toBe("purchase"); expect(keyEvents[0]?.eventName).toBe("purchase");
expect(dimensions[0]?.parameterName).toBe("content_type"); expect(dimensions[0]?.parameterName).toBe("content_type");
expect(metrics[0]?.parameterName).toBe("quality_score"); expect(metrics[0]?.parameterName).toBe("quality_score");

View File

@ -66,15 +66,16 @@ const dataStreamsResponseSchema = z.object({
nextPageToken: z.string().optional(), nextPageToken: z.string().optional(),
}); });
const enhancedMeasurementSettingsSchema = z.object({ const enhancedMeasurementSettingsSchema = z.object({
streamEnabled: z.boolean(), // ProtoJSON omits scalar fields at their default values.
scrollsEnabled: z.boolean(), streamEnabled: z.boolean().default(false),
outboundClicksEnabled: z.boolean(), scrollsEnabled: z.boolean().default(false),
siteSearchEnabled: z.boolean(), outboundClicksEnabled: z.boolean().default(false),
videoEngagementEnabled: z.boolean(), siteSearchEnabled: z.boolean().default(false),
fileDownloadsEnabled: z.boolean(), videoEngagementEnabled: z.boolean().default(false),
pageChangesEnabled: z.boolean(), fileDownloadsEnabled: z.boolean().default(false),
formInteractionsEnabled: z.boolean(), pageChangesEnabled: z.boolean().default(false),
searchQueryParameter: z.string(), formInteractionsEnabled: z.boolean().default(false),
searchQueryParameter: z.string().default(""),
uriQueryParameter: z.string().optional().default(""), uriQueryParameter: z.string().optional().default(""),
}); });
const keyEventSchema = z.object({ const keyEventSchema = z.object({