@iann29/rastro 0.4.0 → 0.5.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 (92) hide show
  1. package/README.md +122 -17
  2. package/agent/integration.md +26 -10
  3. package/agent/manifest.json +10 -5
  4. package/agent/manifest.schema.json +14 -5
  5. package/dist/client/federation.d.ts +28 -8
  6. package/dist/client/federation.d.ts.map +1 -1
  7. package/dist/client/federation.js +12 -1
  8. package/dist/client/federation.js.map +1 -1
  9. package/dist/client/index.d.ts +262 -9
  10. package/dist/client/index.d.ts.map +1 -1
  11. package/dist/client/index.js +119 -2
  12. package/dist/client/index.js.map +1 -1
  13. package/dist/component/_generated/api.d.ts +6 -0
  14. package/dist/component/_generated/api.d.ts.map +1 -1
  15. package/dist/component/_generated/api.js.map +1 -1
  16. package/dist/component/_generated/component.d.ts +71 -1
  17. package/dist/component/_generated/component.d.ts.map +1 -1
  18. package/dist/component/constants.d.ts +2 -0
  19. package/dist/component/constants.d.ts.map +1 -1
  20. package/dist/component/constants.js +7 -0
  21. package/dist/component/constants.js.map +1 -1
  22. package/dist/component/coverage.d.ts +1 -0
  23. package/dist/component/coverage.d.ts.map +1 -1
  24. package/dist/component/coverage.js +6 -1
  25. package/dist/component/coverage.js.map +1 -1
  26. package/dist/component/eventStore.d.ts +2 -0
  27. package/dist/component/eventStore.d.ts.map +1 -1
  28. package/dist/component/http.d.ts.map +1 -1
  29. package/dist/component/http.js +51 -1
  30. package/dist/component/http.js.map +1 -1
  31. package/dist/component/ingest.d.ts +2 -0
  32. package/dist/component/ingest.d.ts.map +1 -1
  33. package/dist/component/ingest.js +42 -3
  34. package/dist/component/ingest.js.map +1 -1
  35. package/dist/component/origin.d.ts +70 -0
  36. package/dist/component/origin.d.ts.map +1 -0
  37. package/dist/component/origin.js +230 -0
  38. package/dist/component/origin.js.map +1 -0
  39. package/dist/component/platforms.d.ts +33 -0
  40. package/dist/component/platforms.d.ts.map +1 -0
  41. package/dist/component/platforms.js +328 -0
  42. package/dist/component/platforms.js.map +1 -0
  43. package/dist/component/reports.d.ts +27 -72
  44. package/dist/component/reports.d.ts.map +1 -1
  45. package/dist/component/reports.js +51 -10
  46. package/dist/component/reports.js.map +1 -1
  47. package/dist/component/sanitize.d.ts +5 -0
  48. package/dist/component/sanitize.d.ts.map +1 -1
  49. package/dist/component/sanitize.js +33 -1
  50. package/dist/component/sanitize.js.map +1 -1
  51. package/dist/component/schema.d.ts +62 -7
  52. package/dist/component/schema.js +16 -1
  53. package/dist/component/schema.js.map +1 -1
  54. package/dist/component/trackedLinks.d.ts +91 -0
  55. package/dist/component/trackedLinks.d.ts.map +1 -0
  56. package/dist/component/trackedLinks.js +314 -0
  57. package/dist/component/trackedLinks.js.map +1 -0
  58. package/dist/component/useragent.d.ts +6 -0
  59. package/dist/component/useragent.d.ts.map +1 -1
  60. package/dist/component/useragent.js +9 -0
  61. package/dist/component/useragent.js.map +1 -1
  62. package/dist/component/validators.d.ts +51 -11
  63. package/dist/component/validators.d.ts.map +1 -1
  64. package/dist/component/validators.js +35 -1
  65. package/dist/component/validators.js.map +1 -1
  66. package/dist/tracker/generated.d.ts +6 -6
  67. package/dist/tracker/generated.d.ts.map +1 -1
  68. package/dist/tracker/generated.js +6 -6
  69. package/dist/tracker/generated.js.map +1 -1
  70. package/dist/tracker/tracker.d.ts +1 -0
  71. package/dist/tracker/tracker.d.ts.map +1 -1
  72. package/dist/tracker/tracker.js +16 -4
  73. package/dist/tracker/tracker.js.map +1 -1
  74. package/dist/tracker.min.js +1 -1
  75. package/docs/upgrading.md +152 -19
  76. package/llms.txt +6 -1
  77. package/package.json +2 -2
  78. package/src/component/_generated/api.ts +6 -0
  79. package/src/component/_generated/component.ts +152 -1
  80. package/src/component/constants.ts +7 -0
  81. package/src/component/coverage.ts +7 -1
  82. package/src/component/http.ts +56 -1
  83. package/src/component/ingest.ts +54 -1
  84. package/src/component/origin.ts +273 -0
  85. package/src/component/platforms.ts +359 -0
  86. package/src/component/reports.ts +74 -10
  87. package/src/component/sanitize.ts +39 -1
  88. package/src/component/schema.ts +18 -0
  89. package/src/component/trackedLinks.ts +384 -0
  90. package/src/component/useragent.ts +11 -0
  91. package/src/component/validators.ts +71 -0
  92. package/src/tracker/generated.ts +6 -6
@@ -0,0 +1,328 @@
1
+ /**
2
+ * The closed table origin.ts classifies against. Bump the version whenever a
3
+ * row changes, and add a corpus case (origin.test.ts) for the change.
4
+ */
5
+ export const PLATFORM_TABLE_VERSION = 1;
6
+ // Ordered for `inAppPlatform`: the first row whose marker matches wins, so
7
+ // Messenger (its iOS agent carries `FBAN/`) precedes Facebook and Threads
8
+ // precedes Instagram. Sources per row: "spec" is the approved proposal's
9
+ // table; the rest is each platform's own domains, link shims, and Play Store
10
+ // package ids, and in-app agents as the apps send them.
11
+ export const PLATFORMS = [
12
+ // Social.
13
+ {
14
+ // Threads: spec (threads.net → threads.com); agent is the app's codename.
15
+ id: "threads",
16
+ channel: "organic_social",
17
+ domains: ["threads.net", "threads.com"],
18
+ packages: ["com.instagram.barcelona"],
19
+ agent: /Barcelona/,
20
+ },
21
+ {
22
+ // spec.
23
+ id: "instagram",
24
+ channel: "organic_social",
25
+ domains: ["instagram.com"],
26
+ packages: ["com.instagram.android"],
27
+ agent: /Instagram/,
28
+ aliases: ["ig", "insta"],
29
+ },
30
+ {
31
+ // spec; + com.facebook.mlite (Messenger Lite), "msg" is Meta's
32
+ // {{site_source_name}} value for Messenger placements.
33
+ id: "messenger",
34
+ channel: "messaging",
35
+ domains: ["messenger.com", "m.me"],
36
+ packages: ["com.facebook.orca", "com.facebook.mlite"],
37
+ agent: /Orca-Android|MessengerLite|MessengerForiOS/,
38
+ aliases: ["msg"],
39
+ },
40
+ {
41
+ // spec; + fb.watch (video short links).
42
+ id: "facebook",
43
+ channel: "organic_social",
44
+ domains: ["facebook.com", "fb.com", "fb.me", "fb.watch"],
45
+ packages: ["com.facebook.katana", "com.facebook.lite"],
46
+ agent: /FBAN\/|FBAV\/|FB_IAB/,
47
+ aliases: ["fb", "face"],
48
+ },
49
+ {
50
+ // spec: only an `fbclid` with nothing that tells Facebook from Instagram.
51
+ id: "meta",
52
+ channel: "organic_social",
53
+ },
54
+ {
55
+ // spec; + TikTok Lite (com.zhiliaoapp.musically.go).
56
+ id: "tiktok",
57
+ channel: "organic_social",
58
+ domains: ["tiktok.com"],
59
+ packages: [
60
+ "com.zhiliaoapp.musically",
61
+ "com.ss.android.ugc.trill",
62
+ "com.zhiliaoapp.musically.go",
63
+ ],
64
+ agent: /BytedanceWebview|musical_ly|TikTok/,
65
+ aliases: ["tt"],
66
+ },
67
+ {
68
+ // spec.
69
+ id: "kwai",
70
+ channel: "organic_social",
71
+ domains: ["kwai.com", "kwai-video.com", "kw.ai"],
72
+ packages: ["com.kwai.video"],
73
+ agent: /Kwai/,
74
+ },
75
+ {
76
+ // spec.
77
+ id: "youtube",
78
+ channel: "organic_social",
79
+ domains: ["youtube.com", "youtu.be"],
80
+ packages: ["com.google.android.youtube"],
81
+ aliases: ["yt"],
82
+ },
83
+ {
84
+ // spec; + TwitterAndroid (the Android app's agent).
85
+ id: "x",
86
+ channel: "organic_social",
87
+ domains: ["x.com", "twitter.com", "t.co"],
88
+ packages: ["com.twitter.android"],
89
+ agent: /Twitter for |TwitterAndroid/,
90
+ aliases: ["twitter"],
91
+ },
92
+ {
93
+ // spec.
94
+ id: "linkedin",
95
+ channel: "organic_social",
96
+ domains: ["linkedin.com", "lnkd.in"],
97
+ packages: ["com.linkedin.android"],
98
+ agent: /LinkedInApp/,
99
+ aliases: ["li"],
100
+ },
101
+ {
102
+ id: "pinterest",
103
+ channel: "organic_social",
104
+ domains: ["pinterest.com", "pin.it"],
105
+ packages: ["com.pinterest"],
106
+ agent: /Pinterest\//,
107
+ aliases: ["pin"],
108
+ },
109
+ {
110
+ id: "reddit",
111
+ channel: "organic_social",
112
+ domains: ["reddit.com", "redd.it"],
113
+ packages: ["com.reddit.frontpage"],
114
+ },
115
+ {
116
+ id: "snapchat",
117
+ channel: "organic_social",
118
+ domains: ["snapchat.com"],
119
+ packages: ["com.snapchat.android"],
120
+ agent: /Snapchat/,
121
+ aliases: ["snap"],
122
+ },
123
+ // Messaging.
124
+ {
125
+ // spec; + wl.co (WhatsApp's link shim, l.wl.co).
126
+ id: "whatsapp",
127
+ channel: "messaging",
128
+ domains: ["whatsapp.com", "wa.me", "wl.co"],
129
+ packages: ["com.whatsapp", "com.whatsapp.w4b"],
130
+ aliases: ["wa", "zap", "whats"],
131
+ },
132
+ {
133
+ // spec; + Telegram X (org.thunderdog.challegram).
134
+ id: "telegram",
135
+ channel: "messaging",
136
+ domains: ["t.me", "telegram.me", "telegram.org"],
137
+ packages: ["org.telegram.messenger", "org.thunderdog.challegram"],
138
+ aliases: ["tg"],
139
+ },
140
+ {
141
+ id: "discord",
142
+ channel: "messaging",
143
+ domains: ["discord.com", "discordapp.com", "discord.gg"],
144
+ packages: ["com.discord"],
145
+ },
146
+ {
147
+ // The Android package is `com.Slack`; referrer hosts arrive lowercase.
148
+ id: "slack",
149
+ channel: "messaging",
150
+ domains: ["slack.com"],
151
+ packages: ["com.slack"],
152
+ },
153
+ {
154
+ id: "line",
155
+ channel: "messaging",
156
+ domains: ["line.me"],
157
+ packages: ["jp.naver.line.android"],
158
+ agent: / Line\//,
159
+ },
160
+ // Search. Google's country domains match one pattern, not a suffix, so
161
+ // mail, docs, drive and every other google.com role host stay out of it.
162
+ {
163
+ // spec: google.<tld>, googleadservices.com, the Google app and GSA/.
164
+ id: "google",
165
+ channel: "organic_search",
166
+ hostPattern: /^(?:www\.)?google\.[a-z.]{2,7}$/,
167
+ domains: ["news.google.com"],
168
+ paidDomains: ["googleadservices.com"],
169
+ packages: ["com.google.android.googlequicksearchbox"],
170
+ agent: /GSA\//,
171
+ paidAliases: ["gads", "adwords", "google-ads", "google_ads", "googleads"],
172
+ },
173
+ {
174
+ id: "bing",
175
+ channel: "organic_search",
176
+ domains: ["bing.com"],
177
+ packages: ["com.microsoft.bing"],
178
+ },
179
+ {
180
+ id: "duckduckgo",
181
+ channel: "organic_search",
182
+ domains: ["duckduckgo.com"],
183
+ packages: ["com.duckduckgo.mobile.android"],
184
+ aliases: ["ddg"],
185
+ },
186
+ {
187
+ // Search hosts only: yahoo.com itself is a portal, mail is yahoo_mail.
188
+ id: "yahoo",
189
+ channel: "organic_search",
190
+ domains: ["search.yahoo.com", "search.yahoo.co.jp"],
191
+ },
192
+ {
193
+ id: "ecosia",
194
+ channel: "organic_search",
195
+ domains: ["ecosia.org"],
196
+ packages: ["com.ecosia.android"],
197
+ },
198
+ {
199
+ id: "yandex",
200
+ channel: "organic_search",
201
+ domains: ["yandex.ru", "yandex.com", "ya.ru"],
202
+ },
203
+ {
204
+ id: "baidu",
205
+ channel: "organic_search",
206
+ domains: ["baidu.com"],
207
+ },
208
+ // E-mail.
209
+ {
210
+ // spec.
211
+ id: "gmail",
212
+ channel: "email",
213
+ domains: ["mail.google.com"],
214
+ packages: ["com.google.android.gm"],
215
+ },
216
+ {
217
+ id: "outlook",
218
+ channel: "email",
219
+ domains: [
220
+ "outlook.com",
221
+ "outlook.live.com",
222
+ "outlook.office.com",
223
+ "outlook.office365.com",
224
+ ],
225
+ packages: ["com.microsoft.office.outlook"],
226
+ aliases: ["hotmail"],
227
+ },
228
+ {
229
+ id: "yahoo_mail",
230
+ channel: "email",
231
+ domains: ["mail.yahoo.com"],
232
+ packages: ["com.yahoo.mobile.client.android.mail"],
233
+ aliases: ["yahoomail"],
234
+ },
235
+ // AI assistants.
236
+ {
237
+ // spec. ChatGPT tags the links it cites with utm_source=chatgpt.com,
238
+ // which the host fallback in origin.ts resolves.
239
+ id: "chatgpt",
240
+ channel: "ai",
241
+ domains: ["chatgpt.com", "chat.openai.com"],
242
+ packages: ["com.openai.chatgpt"],
243
+ aliases: ["openai"],
244
+ },
245
+ {
246
+ id: "perplexity",
247
+ channel: "ai",
248
+ domains: ["perplexity.ai"],
249
+ packages: ["ai.perplexity.app.android"],
250
+ },
251
+ {
252
+ // spec: gemini.google.com; bard is the product's former name.
253
+ id: "gemini",
254
+ channel: "ai",
255
+ domains: ["gemini.google.com", "bard.google.com"],
256
+ packages: ["com.google.android.apps.bard"],
257
+ aliases: ["bard"],
258
+ },
259
+ {
260
+ id: "copilot",
261
+ channel: "ai",
262
+ domains: ["copilot.microsoft.com"],
263
+ packages: ["com.microsoft.copilot"],
264
+ },
265
+ {
266
+ id: "claude",
267
+ channel: "ai",
268
+ domains: ["claude.ai"],
269
+ packages: ["com.anthropic.claude"],
270
+ aliases: ["anthropic"],
271
+ },
272
+ // Display ad servers and a known referral: github.io pages belong to their
273
+ // authors, so only github.com itself is GitHub.
274
+ {
275
+ id: "doubleclick",
276
+ channel: "display",
277
+ domains: ["doubleclick.net"],
278
+ },
279
+ {
280
+ id: "taboola",
281
+ channel: "display",
282
+ domains: ["taboola.com"],
283
+ },
284
+ {
285
+ id: "outbrain",
286
+ channel: "display",
287
+ domains: ["outbrain.com"],
288
+ },
289
+ {
290
+ id: "github",
291
+ channel: "referral",
292
+ domains: ["github.com"],
293
+ packages: ["com.github.android"],
294
+ },
295
+ // A QR code is a tracked link printed off the web: the scan carries no
296
+ // referrer and no app, so the link's own declaration is the only evidence.
297
+ {
298
+ id: "qr",
299
+ channel: "offline",
300
+ aliases: ["qrcode", "qr_code", "qr-code"],
301
+ },
302
+ ];
303
+ /**
304
+ * Click-ID keys the tracker may report by name, in priority order: the ad
305
+ * networks' own ids first, then the organic share ids, `fbclid` last because
306
+ * Meta adds it to organic clicks too. `unknown` platforms take the referrer's.
307
+ */
308
+ export const CLICK_IDS = [
309
+ ["gclid", "google", "paid_search"],
310
+ ["gbraid", "google", "paid_search"],
311
+ ["wbraid", "google", "paid_search"],
312
+ ["msclkid", "bing", "paid_search"],
313
+ ["ttclid", "tiktok", "paid_social"],
314
+ ["twclid", "x", "paid_social"],
315
+ ["li_fat_id", "linkedin", "paid_social"],
316
+ ["ScCid", "snapchat", "paid_social"],
317
+ ["rdt_cid", "reddit", "paid_social"],
318
+ ["dclid", "doubleclick", "display"],
319
+ ["epik", "pinterest", "organic_social"],
320
+ ["srsltid", "google", "organic_search"],
321
+ ["mc_cid", "unknown", "email"],
322
+ ["mc_eid", "unknown", "email"],
323
+ ["_hsenc", "unknown", "email"],
324
+ ["igsh", "instagram", "organic_social"],
325
+ ["igshid", "instagram", "organic_social"],
326
+ ["fbclid", "meta", "organic_social"],
327
+ ];
328
+ //# sourceMappingURL=platforms.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platforms.js","sourceRoot":"","sources":["../../src/component/platforms.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC;AAsBxC,2EAA2E;AAC3E,0EAA0E;AAC1E,yEAAyE;AACzE,6EAA6E;AAC7E,wDAAwD;AACxD,MAAM,CAAC,MAAM,SAAS,GAA2B;IAC/C,UAAU;IACV;QACE,0EAA0E;QAC1E,EAAE,EAAE,SAAS;QACb,OAAO,EAAE,gBAAgB;QACzB,OAAO,EAAE,CAAC,aAAa,EAAE,aAAa,CAAC;QACvC,QAAQ,EAAE,CAAC,yBAAyB,CAAC;QACrC,KAAK,EAAE,WAAW;KACnB;IACD;QACE,QAAQ;QACR,EAAE,EAAE,WAAW;QACf,OAAO,EAAE,gBAAgB;QACzB,OAAO,EAAE,CAAC,eAAe,CAAC;QAC1B,QAAQ,EAAE,CAAC,uBAAuB,CAAC;QACnC,KAAK,EAAE,WAAW;QAClB,OAAO,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC;KACzB;IACD;QACE,+DAA+D;QAC/D,uDAAuD;QACvD,EAAE,EAAE,WAAW;QACf,OAAO,EAAE,WAAW;QACpB,OAAO,EAAE,CAAC,eAAe,EAAE,MAAM,CAAC;QAClC,QAAQ,EAAE,CAAC,mBAAmB,EAAE,oBAAoB,CAAC;QACrD,KAAK,EAAE,4CAA4C;QACnD,OAAO,EAAE,CAAC,KAAK,CAAC;KACjB;IACD;QACE,wCAAwC;QACxC,EAAE,EAAE,UAAU;QACd,OAAO,EAAE,gBAAgB;QACzB,OAAO,EAAE,CAAC,cAAc,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,CAAC;QACxD,QAAQ,EAAE,CAAC,qBAAqB,EAAE,mBAAmB,CAAC;QACtD,KAAK,EAAE,sBAAsB;QAC7B,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC;KACxB;IACD;QACE,0EAA0E;QAC1E,EAAE,EAAE,MAAM;QACV,OAAO,EAAE,gBAAgB;KAC1B;IACD;QACE,qDAAqD;QACrD,EAAE,EAAE,QAAQ;QACZ,OAAO,EAAE,gBAAgB;QACzB,OAAO,EAAE,CAAC,YAAY,CAAC;QACvB,QAAQ,EAAE;YACR,0BAA0B;YAC1B,0BAA0B;YAC1B,6BAA6B;SAC9B;QACD,KAAK,EAAE,oCAAoC;QAC3C,OAAO,EAAE,CAAC,IAAI,CAAC;KAChB;IACD;QACE,QAAQ;QACR,EAAE,EAAE,MAAM;QACV,OAAO,EAAE,gBAAgB;QACzB,OAAO,EAAE,CAAC,UAAU,EAAE,gBAAgB,EAAE,OAAO,CAAC;QAChD,QAAQ,EAAE,CAAC,gBAAgB,CAAC;QAC5B,KAAK,EAAE,MAAM;KACd;IACD;QACE,QAAQ;QACR,EAAE,EAAE,SAAS;QACb,OAAO,EAAE,gBAAgB;QACzB,OAAO,EAAE,CAAC,aAAa,EAAE,UAAU,CAAC;QACpC,QAAQ,EAAE,CAAC,4BAA4B,CAAC;QACxC,OAAO,EAAE,CAAC,IAAI,CAAC;KAChB;IACD;QACE,oDAAoD;QACpD,EAAE,EAAE,GAAG;QACP,OAAO,EAAE,gBAAgB;QACzB,OAAO,EAAE,CAAC,OAAO,EAAE,aAAa,EAAE,MAAM,CAAC;QACzC,QAAQ,EAAE,CAAC,qBAAqB,CAAC;QACjC,KAAK,EAAE,6BAA6B;QACpC,OAAO,EAAE,CAAC,SAAS,CAAC;KACrB;IACD;QACE,QAAQ;QACR,EAAE,EAAE,UAAU;QACd,OAAO,EAAE,gBAAgB;QACzB,OAAO,EAAE,CAAC,cAAc,EAAE,SAAS,CAAC;QACpC,QAAQ,EAAE,CAAC,sBAAsB,CAAC;QAClC,KAAK,EAAE,aAAa;QACpB,OAAO,EAAE,CAAC,IAAI,CAAC;KAChB;IACD;QACE,EAAE,EAAE,WAAW;QACf,OAAO,EAAE,gBAAgB;QACzB,OAAO,EAAE,CAAC,eAAe,EAAE,QAAQ,CAAC;QACpC,QAAQ,EAAE,CAAC,eAAe,CAAC;QAC3B,KAAK,EAAE,aAAa;QACpB,OAAO,EAAE,CAAC,KAAK,CAAC;KACjB;IACD;QACE,EAAE,EAAE,QAAQ;QACZ,OAAO,EAAE,gBAAgB;QACzB,OAAO,EAAE,CAAC,YAAY,EAAE,SAAS,CAAC;QAClC,QAAQ,EAAE,CAAC,sBAAsB,CAAC;KACnC;IACD;QACE,EAAE,EAAE,UAAU;QACd,OAAO,EAAE,gBAAgB;QACzB,OAAO,EAAE,CAAC,cAAc,CAAC;QACzB,QAAQ,EAAE,CAAC,sBAAsB,CAAC;QAClC,KAAK,EAAE,UAAU;QACjB,OAAO,EAAE,CAAC,MAAM,CAAC;KAClB;IAED,aAAa;IACb;QACE,iDAAiD;QACjD,EAAE,EAAE,UAAU;QACd,OAAO,EAAE,WAAW;QACpB,OAAO,EAAE,CAAC,cAAc,EAAE,OAAO,EAAE,OAAO,CAAC;QAC3C,QAAQ,EAAE,CAAC,cAAc,EAAE,kBAAkB,CAAC;QAC9C,OAAO,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC;KAChC;IACD;QACE,kDAAkD;QAClD,EAAE,EAAE,UAAU;QACd,OAAO,EAAE,WAAW;QACpB,OAAO,EAAE,CAAC,MAAM,EAAE,aAAa,EAAE,cAAc,CAAC;QAChD,QAAQ,EAAE,CAAC,wBAAwB,EAAE,2BAA2B,CAAC;QACjE,OAAO,EAAE,CAAC,IAAI,CAAC;KAChB;IACD;QACE,EAAE,EAAE,SAAS;QACb,OAAO,EAAE,WAAW;QACpB,OAAO,EAAE,CAAC,aAAa,EAAE,gBAAgB,EAAE,YAAY,CAAC;QACxD,QAAQ,EAAE,CAAC,aAAa,CAAC;KAC1B;IACD;QACE,uEAAuE;QACvE,EAAE,EAAE,OAAO;QACX,OAAO,EAAE,WAAW;QACpB,OAAO,EAAE,CAAC,WAAW,CAAC;QACtB,QAAQ,EAAE,CAAC,WAAW,CAAC;KACxB;IACD;QACE,EAAE,EAAE,MAAM;QACV,OAAO,EAAE,WAAW;QACpB,OAAO,EAAE,CAAC,SAAS,CAAC;QACpB,QAAQ,EAAE,CAAC,uBAAuB,CAAC;QACnC,KAAK,EAAE,SAAS;KACjB;IAED,uEAAuE;IACvE,yEAAyE;IACzE;QACE,qEAAqE;QACrE,EAAE,EAAE,QAAQ;QACZ,OAAO,EAAE,gBAAgB;QACzB,WAAW,EAAE,iCAAiC;QAC9C,OAAO,EAAE,CAAC,iBAAiB,CAAC;QAC5B,WAAW,EAAE,CAAC,sBAAsB,CAAC;QACrC,QAAQ,EAAE,CAAC,yCAAyC,CAAC;QACrD,KAAK,EAAE,OAAO;QACd,WAAW,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,YAAY,EAAE,WAAW,CAAC;KAC1E;IACD;QACE,EAAE,EAAE,MAAM;QACV,OAAO,EAAE,gBAAgB;QACzB,OAAO,EAAE,CAAC,UAAU,CAAC;QACrB,QAAQ,EAAE,CAAC,oBAAoB,CAAC;KACjC;IACD;QACE,EAAE,EAAE,YAAY;QAChB,OAAO,EAAE,gBAAgB;QACzB,OAAO,EAAE,CAAC,gBAAgB,CAAC;QAC3B,QAAQ,EAAE,CAAC,+BAA+B,CAAC;QAC3C,OAAO,EAAE,CAAC,KAAK,CAAC;KACjB;IACD;QACE,uEAAuE;QACvE,EAAE,EAAE,OAAO;QACX,OAAO,EAAE,gBAAgB;QACzB,OAAO,EAAE,CAAC,kBAAkB,EAAE,oBAAoB,CAAC;KACpD;IACD;QACE,EAAE,EAAE,QAAQ;QACZ,OAAO,EAAE,gBAAgB;QACzB,OAAO,EAAE,CAAC,YAAY,CAAC;QACvB,QAAQ,EAAE,CAAC,oBAAoB,CAAC;KACjC;IACD;QACE,EAAE,EAAE,QAAQ;QACZ,OAAO,EAAE,gBAAgB;QACzB,OAAO,EAAE,CAAC,WAAW,EAAE,YAAY,EAAE,OAAO,CAAC;KAC9C;IACD;QACE,EAAE,EAAE,OAAO;QACX,OAAO,EAAE,gBAAgB;QACzB,OAAO,EAAE,CAAC,WAAW,CAAC;KACvB;IAED,UAAU;IACV;QACE,QAAQ;QACR,EAAE,EAAE,OAAO;QACX,OAAO,EAAE,OAAO;QAChB,OAAO,EAAE,CAAC,iBAAiB,CAAC;QAC5B,QAAQ,EAAE,CAAC,uBAAuB,CAAC;KACpC;IACD;QACE,EAAE,EAAE,SAAS;QACb,OAAO,EAAE,OAAO;QAChB,OAAO,EAAE;YACP,aAAa;YACb,kBAAkB;YAClB,oBAAoB;YACpB,uBAAuB;SACxB;QACD,QAAQ,EAAE,CAAC,8BAA8B,CAAC;QAC1C,OAAO,EAAE,CAAC,SAAS,CAAC;KACrB;IACD;QACE,EAAE,EAAE,YAAY;QAChB,OAAO,EAAE,OAAO;QAChB,OAAO,EAAE,CAAC,gBAAgB,CAAC;QAC3B,QAAQ,EAAE,CAAC,sCAAsC,CAAC;QAClD,OAAO,EAAE,CAAC,WAAW,CAAC;KACvB;IAED,iBAAiB;IACjB;QACE,qEAAqE;QACrE,iDAAiD;QACjD,EAAE,EAAE,SAAS;QACb,OAAO,EAAE,IAAI;QACb,OAAO,EAAE,CAAC,aAAa,EAAE,iBAAiB,CAAC;QAC3C,QAAQ,EAAE,CAAC,oBAAoB,CAAC;QAChC,OAAO,EAAE,CAAC,QAAQ,CAAC;KACpB;IACD;QACE,EAAE,EAAE,YAAY;QAChB,OAAO,EAAE,IAAI;QACb,OAAO,EAAE,CAAC,eAAe,CAAC;QAC1B,QAAQ,EAAE,CAAC,2BAA2B,CAAC;KACxC;IACD;QACE,8DAA8D;QAC9D,EAAE,EAAE,QAAQ;QACZ,OAAO,EAAE,IAAI;QACb,OAAO,EAAE,CAAC,mBAAmB,EAAE,iBAAiB,CAAC;QACjD,QAAQ,EAAE,CAAC,8BAA8B,CAAC;QAC1C,OAAO,EAAE,CAAC,MAAM,CAAC;KAClB;IACD;QACE,EAAE,EAAE,SAAS;QACb,OAAO,EAAE,IAAI;QACb,OAAO,EAAE,CAAC,uBAAuB,CAAC;QAClC,QAAQ,EAAE,CAAC,uBAAuB,CAAC;KACpC;IACD;QACE,EAAE,EAAE,QAAQ;QACZ,OAAO,EAAE,IAAI;QACb,OAAO,EAAE,CAAC,WAAW,CAAC;QACtB,QAAQ,EAAE,CAAC,sBAAsB,CAAC;QAClC,OAAO,EAAE,CAAC,WAAW,CAAC;KACvB;IAED,2EAA2E;IAC3E,gDAAgD;IAChD;QACE,EAAE,EAAE,aAAa;QACjB,OAAO,EAAE,SAAS;QAClB,OAAO,EAAE,CAAC,iBAAiB,CAAC;KAC7B;IACD;QACE,EAAE,EAAE,SAAS;QACb,OAAO,EAAE,SAAS;QAClB,OAAO,EAAE,CAAC,aAAa,CAAC;KACzB;IACD;QACE,EAAE,EAAE,UAAU;QACd,OAAO,EAAE,SAAS;QAClB,OAAO,EAAE,CAAC,cAAc,CAAC;KAC1B;IACD;QACE,EAAE,EAAE,QAAQ;QACZ,OAAO,EAAE,UAAU;QACnB,OAAO,EAAE,CAAC,YAAY,CAAC;QACvB,QAAQ,EAAE,CAAC,oBAAoB,CAAC;KACjC;IAED,uEAAuE;IACvE,2EAA2E;IAC3E;QACE,EAAE,EAAE,IAAI;QACR,OAAO,EAAE,SAAS;QAClB,OAAO,EAAE,CAAC,QAAQ,EAAE,SAAS,EAAE,SAAS,CAAC;KAC1C;CACF,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,SAAS,GAElB;IACF,CAAC,OAAO,EAAE,QAAQ,EAAE,aAAa,CAAC;IAClC,CAAC,QAAQ,EAAE,QAAQ,EAAE,aAAa,CAAC;IACnC,CAAC,QAAQ,EAAE,QAAQ,EAAE,aAAa,CAAC;IACnC,CAAC,SAAS,EAAE,MAAM,EAAE,aAAa,CAAC;IAClC,CAAC,QAAQ,EAAE,QAAQ,EAAE,aAAa,CAAC;IACnC,CAAC,QAAQ,EAAE,GAAG,EAAE,aAAa,CAAC;IAC9B,CAAC,WAAW,EAAE,UAAU,EAAE,aAAa,CAAC;IACxC,CAAC,OAAO,EAAE,UAAU,EAAE,aAAa,CAAC;IACpC,CAAC,SAAS,EAAE,QAAQ,EAAE,aAAa,CAAC;IACpC,CAAC,OAAO,EAAE,aAAa,EAAE,SAAS,CAAC;IACnC,CAAC,MAAM,EAAE,WAAW,EAAE,gBAAgB,CAAC;IACvC,CAAC,SAAS,EAAE,QAAQ,EAAE,gBAAgB,CAAC;IACvC,CAAC,QAAQ,EAAE,SAAS,EAAE,OAAO,CAAC;IAC9B,CAAC,QAAQ,EAAE,SAAS,EAAE,OAAO,CAAC;IAC9B,CAAC,QAAQ,EAAE,SAAS,EAAE,OAAO,CAAC;IAC9B,CAAC,MAAM,EAAE,WAAW,EAAE,gBAAgB,CAAC;IACvC,CAAC,QAAQ,EAAE,WAAW,EAAE,gBAAgB,CAAC;IACzC,CAAC,QAAQ,EAAE,MAAM,EAAE,gBAAgB,CAAC;CACrC,CAAC"}
@@ -1,4 +1,4 @@
1
- import type { Id } from "./_generated/dataModel.js";
1
+ import type { Doc, Id } from "./_generated/dataModel.js";
2
2
  export declare const overview: import("convex/server").RegisteredQuery<"public", {
3
3
  from: number;
4
4
  interval?: "day" | "hour" | undefined;
@@ -75,6 +75,21 @@ export declare const overview: import("convex/server").RegisteredQuery<"public",
75
75
  count: number;
76
76
  revenueCents: number;
77
77
  }[];
78
+ topPlatforms: {
79
+ value: string;
80
+ count: number;
81
+ revenueCents: number;
82
+ }[];
83
+ topChannels: {
84
+ value: string;
85
+ count: number;
86
+ revenueCents: number;
87
+ }[];
88
+ topEvidence: {
89
+ value: string;
90
+ count: number;
91
+ revenueCents: number;
92
+ }[];
78
93
  metadata: {
79
94
  visitors: {
80
95
  basis: "bucketOccurrences" | "estimatedUnique";
@@ -94,6 +109,9 @@ export declare const overview: import("convex/server").RegisteredQuery<"public",
94
109
  topGoals: "goalCompletionVolume";
95
110
  topMediums: "eventVolume" | "sessions";
96
111
  topOutbound: "eventVolume";
112
+ topPlatforms: "eventVolume" | "sessions";
113
+ topChannels: "eventVolume" | "sessions";
114
+ topEvidence: "eventVolume" | "sessions";
97
115
  };
98
116
  dimensionsSince: number | null;
99
117
  engagement: "counted" | "unavailable";
@@ -227,45 +245,12 @@ export declare const siteMap: import("convex/server").RegisteredQuery<"public",
227
245
  };
228
246
  };
229
247
  }>>;
248
+ type SessionRow = Omit<Doc<"sessions">, "geoLookupAttemptedAt" | "lastPageviewAt">;
230
249
  /** Metadata for a selected session, independent of list pagination. */
231
250
  export declare const getSession: import("convex/server").RegisteredQuery<"public", {
232
251
  sessionId: string;
233
252
  siteId: import("convex/values").GenericId<"sites">;
234
- }, Promise<{
235
- _creationTime: number;
236
- _id: import("convex/values").GenericId<"sessions">;
237
- affiliateAttributedAt?: number | undefined;
238
- affiliateExpiresAt?: number | undefined;
239
- affiliateId?: import("convex/values").GenericId<"affiliates"> | undefined;
240
- affiliateSlug?: string | undefined;
241
- browser: string;
242
- city?: string | undefined;
243
- conversionCount: number;
244
- country?: string | undefined;
245
- currency?: string | undefined;
246
- device: string;
247
- durationMs: number;
248
- entryPath: string;
249
- eventCount: number;
250
- exitPath: string;
251
- lastSeenAt: number;
252
- latitude?: number | undefined;
253
- longitude?: number | undefined;
254
- newVisitor?: boolean | undefined;
255
- os: string;
256
- pageviewCount: number;
257
- referrer?: string | undefined;
258
- revenueCents: number;
259
- sessionId: string;
260
- siteId: import("convex/values").GenericId<"sites">;
261
- source: string;
262
- startedAt: number;
263
- utmCampaign?: string | undefined;
264
- utmMedium?: string | undefined;
265
- utmSource?: string | undefined;
266
- visitorId: string;
267
- visitorKey?: string | undefined;
268
- } | null>>;
253
+ }, Promise<SessionRow | null>>;
269
254
  /** Exact commissions alongside overview's period revenue/conversion totals. */
270
255
  export declare const revenueSummary: import("convex/server").RegisteredQuery<"public", {
271
256
  from: number;
@@ -287,41 +272,7 @@ export declare const listSessions: import("convex/server").RegisteredQuery<"publ
287
272
  siteId: import("convex/values").GenericId<"sites">;
288
273
  to: number;
289
274
  }, Promise<{
290
- page: {
291
- _creationTime: number;
292
- _id: import("convex/values").GenericId<"sessions">;
293
- affiliateAttributedAt?: number | undefined;
294
- affiliateExpiresAt?: number | undefined;
295
- affiliateId?: import("convex/values").GenericId<"affiliates"> | undefined;
296
- affiliateSlug?: string | undefined;
297
- browser: string;
298
- city?: string | undefined;
299
- conversionCount: number;
300
- country?: string | undefined;
301
- currency?: string | undefined;
302
- device: string;
303
- durationMs: number;
304
- entryPath: string;
305
- eventCount: number;
306
- exitPath: string;
307
- lastSeenAt: number;
308
- latitude?: number | undefined;
309
- longitude?: number | undefined;
310
- newVisitor?: boolean | undefined;
311
- os: string;
312
- pageviewCount: number;
313
- referrer?: string | undefined;
314
- revenueCents: number;
315
- sessionId: string;
316
- siteId: import("convex/values").GenericId<"sites">;
317
- source: string;
318
- startedAt: number;
319
- utmCampaign?: string | undefined;
320
- utmMedium?: string | undefined;
321
- utmSource?: string | undefined;
322
- visitorId: string;
323
- visitorKey?: string | undefined;
324
- }[];
275
+ page: SessionRow[];
325
276
  isDone: boolean;
326
277
  continueCursor: string;
327
278
  }>>;
@@ -353,9 +304,11 @@ export declare const sessionJourney: import("convex/server").RegisteredQuery<"pu
353
304
  os: string;
354
305
  device: string;
355
306
  affiliateSlug?: string | undefined;
307
+ clid?: string[] | undefined;
356
308
  currency?: string | undefined;
357
309
  eventId: string;
358
310
  href?: string | undefined;
311
+ inApp?: string | undefined;
359
312
  name?: string | undefined;
360
313
  path: string;
361
314
  properties?: Record<string, string | number | boolean | null> | undefined;
@@ -426,9 +379,11 @@ export declare const visitorJourney: import("convex/server").RegisteredQuery<"pu
426
379
  os: string;
427
380
  device: string;
428
381
  affiliateSlug?: string | undefined;
382
+ clid?: string[] | undefined;
429
383
  currency?: string | undefined;
430
384
  eventId: string;
431
385
  href?: string | undefined;
386
+ inApp?: string | undefined;
432
387
  name?: string | undefined;
433
388
  path: string;
434
389
  properties?: Record<string, string | number | boolean | null> | undefined;
@@ -629,7 +584,7 @@ export declare const dataCoverage: import("convex/server").RegisteredQuery<"publ
629
584
  from: number;
630
585
  to: number;
631
586
  datasets: {
632
- dataset: "affiliates" | "conversions" | "events" | "funnels" | "goals" | "overviewDay" | "overviewHour" | "overviewLocalDay" | "sessions" | "siteMap" | "vitals";
587
+ dataset: "affiliates" | "conversions" | "events" | "funnels" | "goals" | "origin" | "overviewDay" | "overviewHour" | "overviewLocalDay" | "sessions" | "siteMap" | "vitals";
633
588
  coverage: {
634
589
  state: "complete" | "partial" | "retained" | "unavailable";
635
590
  generation: 1 | null;
@@ -1 +1 @@
1
- {"version":3,"file":"reports.d.ts","sourceRoot":"","sources":["../../src/component/reports.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"reports.d.ts","sourceRoot":"","sources":["../../src/component/reports.ts"],"names":[],"mappings":"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"}
@@ -7,6 +7,8 @@ import { fail } from "./errors.js";
7
7
  import { isLocalDayAligned, localDayStart, localDayStarts, localDayTimezone, sharedLocalTimezone, } from "./localTime.js";
8
8
  import { compareJourneyEvents, hydrateEventContexts, loadSessionJourneyEvents, loadVisitorJourneyEvents, } from "./eventStore.js";
9
9
  import { isPlainRecord } from "./guards.js";
10
+ import { classifyOrigin } from "./origin.js";
11
+ import { externalReferrer } from "./sanitize.js";
10
12
  import { affiliateFieldsValidator, eventFieldsValidator, funnelFieldsValidator, goalFieldsValidator, sessionFieldsValidator, vitalMetricValidator, } from "./validators.js";
11
13
  import { resolveVisitorIdentities } from "./visitors.js";
12
14
  import { mergeVitalHistograms, VITAL_ALL, VITAL_METRICS, vitalHistogramPercentile, vitalRatingCounts, } from "./vitals.js";
@@ -145,6 +147,11 @@ export const overview = query({
145
147
  topMediums: v.array(topItemValidator),
146
148
  // Destination hosts of outbound clicks, ranked by clicks.
147
149
  topOutbound: v.array(topItemValidator),
150
+ // The session's origin (origin.ts), ranked like sources: platform ids,
151
+ // channel ids, and the evidence that decided them.
152
+ topPlatforms: v.array(topItemValidator),
153
+ topChannels: v.array(topItemValidator),
154
+ topEvidence: v.array(topItemValidator),
148
155
  metadata: v.object({
149
156
  visitors: v.object({
150
157
  basis: v.union(v.literal("estimatedUnique"), v.literal("bucketOccurrences")),
@@ -164,6 +171,9 @@ export const overview = query({
164
171
  topGoals: v.literal("goalCompletionVolume"),
165
172
  topMediums: breakdownBasisValidator,
166
173
  topOutbound: v.literal("eventVolume"),
174
+ topPlatforms: breakdownBasisValidator,
175
+ topChannels: breakdownBasisValidator,
176
+ topEvidence: breakdownBasisValidator,
167
177
  }),
168
178
  // Since when every site in the request records the medium and outbound
169
179
  // slots; null while one of them has not stamped it. A range that starts
@@ -390,6 +400,9 @@ export const overview = query({
390
400
  topGoals: top("goal", "eventVolume"),
391
401
  topMediums: top("medium", sessionBasis),
392
402
  topOutbound: top("outbound", "eventVolume"),
403
+ topPlatforms: top("platform", sessionBasis),
404
+ topChannels: top("channel", sessionBasis),
405
+ topEvidence: top("evidence", sessionBasis),
393
406
  metadata: {
394
407
  visitors: {
395
408
  basis: visitorBasis,
@@ -409,6 +422,9 @@ export const overview = query({
409
422
  topGoals: "goalCompletionVolume",
410
423
  topMediums: sessionBasis,
411
424
  topOutbound: "eventVolume",
425
+ topPlatforms: sessionBasis,
426
+ topChannels: sessionBasis,
427
+ topEvidence: sessionBasis,
412
428
  },
413
429
  dimensionsSince: controls.every((control) => control?.dimensionsSince !== undefined)
414
430
  ? Math.max(...controls.map((control) => control.dimensionsSince))
@@ -720,6 +736,22 @@ async function readRouteRollups(ctx, siteId, from, to, budget) {
720
736
  }
721
737
  return { rows, completeFrom: cutAt + DAY_MS };
722
738
  }
739
+ /**
740
+ * A session recorded before origins existed, classified on read from what it
741
+ * kept (utm fields, referrer, affiliate) and marked `legacy`: it carries no
742
+ * click IDs or in-app signal, and it never enters the aggregates.
743
+ */
744
+ function withOrigin(session, domains) {
745
+ if (session.platform !== undefined)
746
+ return session;
747
+ const origin = classifyOrigin({
748
+ utmSource: session.utmSource,
749
+ utmMedium: session.utmMedium,
750
+ referrer: externalReferrer(session.referrer, domains),
751
+ affiliate: session.affiliateSlug !== undefined,
752
+ });
753
+ return { ...session, ...origin, evidence: "legacy" };
754
+ }
723
755
  /** Metadata for a selected session, independent of list pagination. */
724
756
  export const getSession = query({
725
757
  args: { siteId: v.id("sites"), sessionId: v.string() },
@@ -732,7 +764,8 @@ export const getSession = query({
732
764
  if (!session)
733
765
  return null;
734
766
  const { geoLookupAttemptedAt: _geo, lastPageviewAt: _pageview, ...result } = session;
735
- return result;
767
+ const site = await ctx.db.get("sites", args.siteId);
768
+ return withOrigin(result, site?.domains ?? []);
736
769
  },
737
770
  });
738
771
  /** Exact commissions alongside overview's period revenue/conversion totals. */
@@ -844,7 +877,8 @@ export const listSessions = query({
844
877
  .order("desc")
845
878
  .take(take)));
846
879
  }
847
- const publicRows = rows.map(({ geoLookupAttemptedAt: _attemptedAt, lastPageviewAt: _lastPageviewAt, ...row }) => row);
880
+ const site = await ctx.db.get("sites", args.siteId);
881
+ const publicRows = rows.map(({ geoLookupAttemptedAt: _attemptedAt, lastPageviewAt: _lastPageviewAt, ...row }) => withOrigin(row, site?.domains ?? []));
848
882
  return keysetPaginationResult(publicRows, pagination, (row) => ({
849
883
  timestamp: row.lastSeenAt,
850
884
  creationTime: row._creationTime,
@@ -1381,7 +1415,7 @@ export const vitalsReport = query({
1381
1415
  };
1382
1416
  },
1383
1417
  });
1384
- const coverageDatasetValidator = v.union(v.literal("overviewHour"), v.literal("overviewDay"), v.literal("overviewLocalDay"), v.literal("events"), v.literal("sessions"), v.literal("conversions"), v.literal("goals"), v.literal("funnels"), v.literal("affiliates"), v.literal("vitals"), v.literal("siteMap"));
1418
+ const coverageDatasetValidator = v.union(v.literal("overviewHour"), v.literal("overviewDay"), v.literal("overviewLocalDay"), v.literal("events"), v.literal("sessions"), v.literal("conversions"), v.literal("goals"), v.literal("funnels"), v.literal("affiliates"), v.literal("vitals"), v.literal("siteMap"), v.literal("origin"));
1385
1419
  export const dataCoverage = query({
1386
1420
  args: {
1387
1421
  siteId: v.id("sites"),
@@ -1411,6 +1445,7 @@ export const dataCoverage = query({
1411
1445
  "affiliates",
1412
1446
  "vitals",
1413
1447
  "siteMap",
1448
+ "origin",
1414
1449
  ];
1415
1450
  return {
1416
1451
  siteId: args.siteId,
@@ -1601,7 +1636,12 @@ async function assertSourceAvailable(ctx, siteIds, sources, from) {
1601
1636
  }
1602
1637
  async function datasetCoverageForRange(ctx, siteId, dataset, from, to) {
1603
1638
  if (dataset === "siteMap") {
1604
- return siteMapDatasetCoverage(ctx, siteId, from, to);
1639
+ return stampedDatasetCoverage(ctx, siteId, from, to, "siteMapSince", siteMapCoverageDataset);
1640
+ }
1641
+ // Origins exist in sessions and aggregate slots from the site's stamp, and
1642
+ // the overview reads them from the daily aggregates retention trims.
1643
+ if (dataset === "origin") {
1644
+ return stampedDatasetCoverage(ctx, siteId, from, to, "originSince", "overviewDay");
1605
1645
  }
1606
1646
  // Vitals have no legacy fallback source; the rollup either covers the range
1607
1647
  // or the coverage states say how much of it exists.
@@ -1635,17 +1675,18 @@ async function datasetCoverageForRange(ctx, siteId, dataset, from, to) {
1635
1675
  return options.sort((left, right) => coverageRank(right.state) - coverageRank(left.state))[0];
1636
1676
  }
1637
1677
  /**
1638
- * The site map's coverage without reading its rows: it starts at the site's
1639
- * `siteMapSince` and ends where retention cut it. The report itself may still
1640
- * narrow the window when the range exceeds its row budget.
1678
+ * A stamped dataset's coverage without reading its rows: it starts at the
1679
+ * site's stamp (`siteMapSince`, `originSince`) and ends where retention cut
1680
+ * it. The site map report may still narrow the window when the range exceeds
1681
+ * its row budget.
1641
1682
  */
1642
- async function siteMapDatasetCoverage(ctx, siteId, from, to) {
1683
+ async function stampedDatasetCoverage(ctx, siteId, from, to, stamp, retainedDataset) {
1643
1684
  const control = await ctx.db
1644
1685
  .query("analyticsCoverage")
1645
1686
  .withIndex("by_siteId", (range) => range.eq("siteId", siteId))
1646
1687
  .unique();
1647
- const since = control?.siteMapSince ?? null;
1648
- const retainedBefore = control?.retained.find((item) => item.dataset === siteMapCoverageDataset)
1688
+ const since = control?.[stamp] ?? null;
1689
+ const retainedBefore = control?.retained.find((item) => item.dataset === retainedDataset)
1649
1690
  ?.before ?? null;
1650
1691
  const unavailable = since === null ||
1651
1692
  to < since ||