@iann29/rastro 0.10.0 → 0.10.1

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 (96) hide show
  1. package/agent/manifest.json +1 -1
  2. package/dist/client/index.d.ts +6 -1
  3. package/dist/client/index.d.ts.map +1 -1
  4. package/dist/client/index.js +9 -3
  5. package/dist/client/index.js.map +1 -1
  6. package/dist/component/_generated/component.d.ts +1 -0
  7. package/dist/component/_generated/component.d.ts.map +1 -1
  8. package/dist/component/meta.d.ts +11 -5
  9. package/dist/component/meta.d.ts.map +1 -1
  10. package/dist/component/meta.js +81 -25
  11. package/dist/component/meta.js.map +1 -1
  12. package/dist/component/pipeline.d.ts +1 -0
  13. package/dist/component/pipeline.d.ts.map +1 -1
  14. package/dist/component/pipeline.js +18 -5
  15. package/dist/component/pipeline.js.map +1 -1
  16. package/dist/tracker/generated.d.ts +1 -1
  17. package/dist/tracker/generated.js +1 -1
  18. package/dist/ui/index.d.ts +2 -2
  19. package/dist/ui/index.d.ts.map +1 -1
  20. package/dist/ui/index.js +3 -2
  21. package/dist/ui/index.js.map +1 -1
  22. package/dist/ui/integrations/AccountPicker.d.ts.map +1 -1
  23. package/dist/ui/integrations/AccountPicker.js +6 -2
  24. package/dist/ui/integrations/AccountPicker.js.map +1 -1
  25. package/dist/ui/integrations/ClientCards.d.ts.map +1 -1
  26. package/dist/ui/integrations/ClientCards.js +6 -2
  27. package/dist/ui/integrations/ClientCards.js.map +1 -1
  28. package/dist/ui/integrations/ClientsTable.d.ts.map +1 -1
  29. package/dist/ui/integrations/ClientsTable.js +26 -10
  30. package/dist/ui/integrations/ClientsTable.js.map +1 -1
  31. package/dist/ui/integrations/Connect.d.ts +8 -2
  32. package/dist/ui/integrations/Connect.d.ts.map +1 -1
  33. package/dist/ui/integrations/Connect.js +18 -5
  34. package/dist/ui/integrations/Connect.js.map +1 -1
  35. package/dist/ui/integrations/Connection.d.ts.map +1 -1
  36. package/dist/ui/integrations/Connection.js +18 -4
  37. package/dist/ui/integrations/Connection.js.map +1 -1
  38. package/dist/ui/integrations/Dialogs.d.ts +4 -1
  39. package/dist/ui/integrations/Dialogs.d.ts.map +1 -1
  40. package/dist/ui/integrations/Dialogs.js +13 -4
  41. package/dist/ui/integrations/Dialogs.js.map +1 -1
  42. package/dist/ui/integrations/EventsFeed.d.ts.map +1 -1
  43. package/dist/ui/integrations/EventsFeed.js +5 -1
  44. package/dist/ui/integrations/EventsFeed.js.map +1 -1
  45. package/dist/ui/integrations/EventsSheet.d.ts +9 -3
  46. package/dist/ui/integrations/EventsSheet.d.ts.map +1 -1
  47. package/dist/ui/integrations/EventsSheet.js +20 -5
  48. package/dist/ui/integrations/EventsSheet.js.map +1 -1
  49. package/dist/ui/integrations/Icons.d.ts +2 -0
  50. package/dist/ui/integrations/Icons.d.ts.map +1 -1
  51. package/dist/ui/integrations/Icons.js +2 -0
  52. package/dist/ui/integrations/Icons.js.map +1 -1
  53. package/dist/ui/integrations/IntegrationsView.d.ts +10 -9
  54. package/dist/ui/integrations/IntegrationsView.d.ts.map +1 -1
  55. package/dist/ui/integrations/IntegrationsView.js +43 -15
  56. package/dist/ui/integrations/IntegrationsView.js.map +1 -1
  57. package/dist/ui/integrations/Overlay.js +1 -1
  58. package/dist/ui/integrations/Overlay.js.map +1 -1
  59. package/dist/ui/integrations/Partner.d.ts +14 -0
  60. package/dist/ui/integrations/Partner.d.ts.map +1 -0
  61. package/dist/ui/integrations/Partner.js +38 -0
  62. package/dist/ui/integrations/Partner.js.map +1 -0
  63. package/dist/ui/integrations/RowMenu.js +1 -1
  64. package/dist/ui/integrations/RowMenu.js.map +1 -1
  65. package/dist/ui/integrations/audience.d.ts +12 -0
  66. package/dist/ui/integrations/audience.d.ts.map +1 -0
  67. package/dist/ui/integrations/audience.js +12 -0
  68. package/dist/ui/integrations/audience.js.map +1 -0
  69. package/dist/ui/integrations/index.d.ts +2 -2
  70. package/dist/ui/integrations/index.d.ts.map +1 -1
  71. package/dist/ui/integrations/index.js +1 -1
  72. package/dist/ui/integrations/index.js.map +1 -1
  73. package/dist/ui/integrations/{overlay.d.ts → modal.d.ts} +1 -1
  74. package/dist/ui/integrations/modal.d.ts.map +1 -0
  75. package/dist/ui/integrations/{overlay.js → modal.js} +1 -1
  76. package/dist/ui/integrations/modal.js.map +1 -0
  77. package/dist/ui/integrations/model.d.ts +18 -3
  78. package/dist/ui/integrations/model.d.ts.map +1 -1
  79. package/dist/ui/integrations/model.js +35 -2
  80. package/dist/ui/integrations/model.js.map +1 -1
  81. package/dist/ui/integrations/types.d.ts +53 -3
  82. package/dist/ui/integrations/types.d.ts.map +1 -1
  83. package/dist/ui/sample.d.ts +62 -0
  84. package/dist/ui/sample.d.ts.map +1 -1
  85. package/dist/ui/sample.js +21 -0
  86. package/dist/ui/sample.js.map +1 -1
  87. package/dist/ui/ui.css +73 -5
  88. package/docs/meta-ads.md +53 -4
  89. package/docs/upgrading.md +21 -0
  90. package/package.json +1 -1
  91. package/src/component/_generated/component.ts +1 -0
  92. package/src/component/meta.ts +95 -31
  93. package/src/component/pipeline.ts +23 -5
  94. package/src/tracker/generated.ts +1 -1
  95. package/dist/ui/integrations/overlay.d.ts.map +0 -1
  96. package/dist/ui/integrations/overlay.js.map +0 -1
package/docs/meta-ads.md CHANGED
@@ -348,8 +348,12 @@ app.use(rastro, {
348
348
 
349
349
  - On the federated path a dashboard never takes or undoes what another owner on
350
350
  the host made: linking an account another owner linked to the site, unlinking
351
- another owner's link, and replacing or removing another owner's pixel are each
352
- `CONFLICT`. The host's own `Rastro` methods can do all of it.
351
+ another owner's link, replacing or removing another owner's pixel, and saving
352
+ the event map of a site whose pixel another owner set are each `CONFLICT`.
353
+ Whoever set the pixel decides which columns reach it. The host's own `Rastro`
354
+ methods can do all of it, or refuse the same way when asked: `onlyOwn` on
355
+ `linkSiteAdAccount` and `setSitePixel`, an `ownerKey` on
356
+ `unlinkSiteAdAccount`, `removeSitePixel` and `setEventMap`.
353
357
  - A lead's ad click id stays in the host's deployment, as before; no report
354
358
  returns it.
355
359
  - Each conversion carries an `eventId` derived from the lead and the event, so a
@@ -386,7 +390,10 @@ await rastro.linkSiteAdAccount(ctx, {
386
390
  and `META_TOKEN_INVALID` when Meta refuses the token.
387
391
  - `listMetaAdAccounts` (action) reads the accounts from Meta again and refreshes
388
392
  the listing a link is checked against. `removeMetaConnection` forgets the
389
- token and unlinks every account it fed.
393
+ owner: its token, every account it fed, and every pixel it set, the ones with
394
+ their own token (plan B, `setBy`) included. An owner with only plan B pixels
395
+ and no connection loses those pixels all the same; `removed` says whether
396
+ anything went.
390
397
  - `linkSiteAdAccount` (mutation) links a site to one of the listed accounts, at
391
398
  most 20 per site and 500 per connection. **An ad account feeds one site**: its
392
399
  spend is that client's, so linking it to a second site fails with `CONFLICT`
@@ -574,7 +581,10 @@ const map = await rastro.eventMap(ctx, { siteId, now: Date.now() });
574
581
  - `setEventMap` replaces the whole map: each declared column maps to `Lead`,
575
582
  `QualifiedLead`, `Schedule` or null. A key the pipeline does not declare is
576
583
  `INVALID_ARGUMENT`. `sendLeadEvent` turns `Lead` on for every new lead and is
577
- kept on the pixel too.
584
+ kept on the pixel too. With `ownerKey`, a site whose pixel another owner (or
585
+ the host, without an owner) set is a `CONFLICT`: the pixel's owner decides its
586
+ events. A site without a pixel takes any owner's map. The federated
587
+ `setMetaEventMap` always passes the dashboard connection's owner.
578
588
  - `eventMap({ siteId, now? })` answers the columns with `key`, `name`, `color`,
579
589
  `group`, `event` and `monthCount`: the distinct leads that entered the column
580
590
  in the 30 UTC days up to `now` (a lead that leaves and comes back counts
@@ -744,3 +754,42 @@ hash of `br`), `custom_data.value` and `currency` on `Purchase`, and the pixel's
744
754
 
745
755
  Under `RASTRO_META_FAKE=true` every send is accepted (a token containing
746
756
  `invalid` is refused like an expired one) and nothing leaves the deployment.
757
+
758
+ ## The Integrações screen (`IntegrationsView`)
759
+
760
+ `@iann29/rastro/ui` ships the screen every surface embeds: the Meta login, each
761
+ site's ad account and pixel, and the events sheet that maps board columns to
762
+ Meta events. It is pure, like the other views: the host passes `connection`
763
+ (`metaConnection`), `sites`, `status` (`meta.status` with `ownerKey`, so each
764
+ link and the pixel carry `own`), `eventMaps` and `conversions`, and turns every
765
+ callback (`onConnect`, `onLinkAccount`, `onSetPixel`, `onSaveEventMap`, …) into
766
+ its own call. `@iann29/rastro/ui/sample` has every state in
767
+ `sampleIntegrations`.
768
+
769
+ It speaks to two readers through `audience`:
770
+
771
+ - `"agency"` (the default): one Meta login for many clients, a table of clients
772
+ with a filter, the feed across every client's pixel. The Rastro dashboard and
773
+ uze.ai's partner portal render it.
774
+ - `"business"`: one company connecting its own Meta ("Conexão Meta"). It shows
775
+ the first site only, as a one-row "Sua conta de anúncio" (no filter, no
776
+ currency column), and its copy names the company and never an agency or
777
+ clients. `productName` says who reads the spend and warns the pixel ("o uze lê
778
+ o gasto"; "Rastro" by default). With no site yet it shows the login alone, for
779
+ a host that makes the company's site on connecting.
780
+
781
+ Whatever another owner of the site linked (`own: false`) shows a lock, "Ligado
782
+ pelo <otherOwnerLabel>", and its row offers no unlink or pixel swap; its events
783
+ sheet reads "Ver eventos" and is read only, since the pixel's owner decides them
784
+ (`setMetaEventMap` refuses with `CONFLICT`). In business mode a `partner`
785
+ (`{ name, allowed, onAllowedChange?, busy? }`) draws the partner's card on top,
786
+ "O parceiro Gio cuida dos seus anúncios na Meta", with the company's checkbox
787
+ "Deixar Gio ver as campanhas" when `onAllowedChange` is given, and, unless the
788
+ host passes its own `otherOwnerLabel`, the locks read "Ligado pelo parceiro
789
+ Gio".
790
+
791
+ In agency mode, `onCopyEventMap(siteIds, map)` adds "Usar o mesmo mapa nos
792
+ outros clientes" to the events sheet. Saving with it checked calls
793
+ `onSaveEventMap` for the client, then `onCopyEventMap` with the other clients
794
+ whose board declares the same columns and whose pixel is not another owner's
795
+ (`eventMapCopyTargets` computes them).
package/docs/upgrading.md CHANGED
@@ -1,5 +1,26 @@
1
1
  # Upgrading Amage Rastro
2
2
 
3
+ ## The business screen and the owner checks (0.10.1)
4
+
5
+ No schema change, env var or re-export. Install `@iann29/rastro@0.10.1` and
6
+ deploy the host. Two behaviors change on purpose:
7
+
8
+ - `setMetaEventMap` (federated) refuses with `CONFLICT` on a site whose pixel
9
+ another owner set: the dashboard no longer rewrites the map of a pixel the
10
+ host's own owner linked. The host's `setEventMap` is unchanged unless it
11
+ passes the new optional `ownerKey`.
12
+ - `removeMetaConnection` (and `removeFederatedMetaConnection`, so revoking a
13
+ dashboard connection) now also removes the pixels the owner set with their own
14
+ token (plan B), not only those of its connection. A host that sets plan B
15
+ pixels for an owner should pass that owner as `setBy` in `setSitePixel`, so
16
+ removing the owner reaches them.
17
+
18
+ Hosts embedding `IntegrationsView` can render it for one company with
19
+ `audience="business"` (and `partner`, `productName`), and offer "Usar o mesmo
20
+ mapa nos outros clientes" with `onCopyEventMap`; see
21
+ [the Integrações screen](meta-ads.md#the-integrações-screen-integrationsview).
22
+ Nothing changes for a host that passes neither.
23
+
3
24
  ## Meta ads, conversions and the Integrações screen (0.10.0)
4
25
 
5
26
  Install `@iann29/rastro@0.10.0` and deploy the consuming host. The release is
package/package.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "bugs": {
7
7
  "url": "https://github.com/amageweb/amage-rastro/issues"
8
8
  },
9
- "version": "0.10.0",
9
+ "version": "0.10.1",
10
10
  "license": "Apache-2.0",
11
11
  "publishConfig": {
12
12
  "access": "public"
@@ -762,6 +762,7 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
762
762
  "internal",
763
763
  {
764
764
  columns: Record<string, "Lead" | "QualifiedLead" | "Schedule" | null>;
765
+ ownerKey?: string;
765
766
  sendLeadEvent: boolean;
766
767
  siteId: string;
767
768
  },
@@ -79,7 +79,8 @@ const TOKEN_EXCHANGE_FAILED =
79
79
  /** How long before a token dies the screens ask for a new login. */
80
80
  const EXPIRY_WARNING_MS = 7 * 86_400_000;
81
81
 
82
- function ownerKeyOf(value: string): string {
82
+ /** An owner key as stored: the host's opaque id, checked. */
83
+ export function ownerKeyOf(value: string): string {
83
84
  try {
84
85
  return sanitizeOpaqueId(value, "ownerKey");
85
86
  } catch (error) {
@@ -699,59 +700,122 @@ async function unlinkRow(
699
700
  }
700
701
 
701
702
  /**
702
- * Forgets the owner's token and unlinks every account it fed. The token goes
703
- * at once (no run can load it after this), its links and pixels in scheduled
704
- * batches.
703
+ * Forgets the owner: its token, every account it fed, and every pixel it set,
704
+ * the ones with their own token (plan B) included. The token goes at once (no
705
+ * run can load it after this), its links and pixels in scheduled batches. An
706
+ * owner with plan B pixels and no connection still loses those pixels.
705
707
  */
706
708
  export const removeConnection = mutation({
707
709
  args: { ownerKey: v.string() },
708
710
  returns: v.object({ removed: v.boolean() }),
709
711
  handler: async (ctx, args) => {
712
+ const ownerKey = ownerKeyOf(args.ownerKey);
710
713
  const connection = await ctx.db
711
714
  .query("metaConnections")
712
- .withIndex("by_ownerKey", (range) =>
713
- range.eq("ownerKey", ownerKeyOf(args.ownerKey)),
714
- )
715
+ .withIndex("by_ownerKey", (range) => range.eq("ownerKey", ownerKey))
715
716
  .unique();
716
- if (!connection) return { removed: false };
717
- await ctx.db.delete("metaConnections", connection._id);
718
- await unlinkConnectionBatch(ctx, connection._id);
719
- return { removed: true };
717
+ if (connection) await ctx.db.delete("metaConnections", connection._id);
718
+ const removedPixels = await removeOwnerBatch(ctx, {
719
+ connectionId: connection?._id,
720
+ ownerKey,
721
+ before: Date.now(),
722
+ });
723
+ return { removed: connection !== null || removedPixels > 0 };
720
724
  },
721
725
  });
722
726
 
723
- async function unlinkConnectionBatch(
727
+ /**
728
+ * One batch of a removed owner: its connection's links and pixels, and the
729
+ * pixels it set (`setBy`) last changed by `before`, so a pixel the same owner
730
+ * sets again after the removal stays. The owner's pixels are walked in
731
+ * creation order from `after`, so every batch moves on even past the ones it
732
+ * keeps. Schedules the next batch while any is left and answers how many
733
+ * pixels this one removed.
734
+ */
735
+ async function removeOwnerBatch(
724
736
  ctx: MutationCtx,
725
- connectionId: Id<"metaConnections">,
737
+ owner: {
738
+ connectionId?: Id<"metaConnections"> | undefined;
739
+ ownerKey?: string | undefined;
740
+ before?: number | undefined;
741
+ after?: number | undefined;
742
+ },
726
743
  ) {
727
- const links = await ctx.db
728
- .query("siteAdAccounts")
729
- .withIndex("by_connectionId", (range) =>
730
- range.eq("connectionId", connectionId),
731
- )
732
- .take(UNLINK_BATCH);
744
+ const { connectionId, ownerKey, before, after } = owner;
745
+ const links = connectionId
746
+ ? await ctx.db
747
+ .query("siteAdAccounts")
748
+ .withIndex("by_connectionId", (range) =>
749
+ range.eq("connectionId", connectionId),
750
+ )
751
+ .take(UNLINK_BATCH)
752
+ : [];
733
753
  for (const link of links) await unlinkRow(ctx, link);
734
754
  // A pixel picked through the connection sent with its token: it goes too.
735
- const pixels = await ctx.db
736
- .query("sitePixels")
737
- .withIndex("by_connectionId", (range) =>
738
- range.eq("connectionId", connectionId),
739
- )
740
- .take(UNLINK_BATCH);
741
- for (const pixel of pixels) await ctx.db.delete("sitePixels", pixel._id);
742
- if (links.length === UNLINK_BATCH || pixels.length === UNLINK_BATCH) {
755
+ const connectionPixels = connectionId
756
+ ? await ctx.db
757
+ .query("sitePixels")
758
+ .withIndex("by_connectionId", (range) =>
759
+ range.eq("connectionId", connectionId),
760
+ )
761
+ .take(UNLINK_BATCH)
762
+ : [];
763
+ for (const pixel of connectionPixels) {
764
+ await ctx.db.delete("sitePixels", pixel._id);
765
+ }
766
+ // So does every pixel the owner set with its own token (plan B), unless it
767
+ // was set again after the removal (`updatedAt` past `before`).
768
+ const ownerPixels =
769
+ ownerKey === undefined || before === undefined
770
+ ? []
771
+ : await ctx.db
772
+ .query("sitePixels")
773
+ .withIndex("by_setBy", (range) =>
774
+ after === undefined
775
+ ? range.eq("setBy", ownerKey)
776
+ : range.eq("setBy", ownerKey).gt("_creationTime", after),
777
+ )
778
+ .take(UNLINK_BATCH);
779
+ // `<=`: a pixel set in the removal's own millisecond, before it, must go;
780
+ // one set again in that same millisecond after it goes too (the rarer case).
781
+ const stale = ownerPixels.filter((pixel) => pixel.updatedAt <= before!);
782
+ for (const pixel of stale) await ctx.db.delete("sitePixels", pixel._id);
783
+ const cursor = ownerPixels.at(-1)?._creationTime;
784
+ if (
785
+ links.length === UNLINK_BATCH ||
786
+ connectionPixels.length === UNLINK_BATCH ||
787
+ ownerPixels.length === UNLINK_BATCH
788
+ ) {
743
789
  await ctx.scheduler.runAfter(0, internal.meta.unlinkConnection, {
744
- connectionId,
790
+ ...(connectionId ? { connectionId } : {}),
791
+ ...(ownerKey === undefined || before === undefined
792
+ ? {}
793
+ : { ownerKey, before }),
794
+ // A full owner batch goes on from its last row; otherwise from where
795
+ // this one started.
796
+ ...(ownerPixels.length === UNLINK_BATCH && cursor !== undefined
797
+ ? { after: cursor }
798
+ : after === undefined
799
+ ? {}
800
+ : { after }),
745
801
  });
746
802
  }
803
+ return connectionPixels.length + stale.length;
747
804
  }
748
805
 
749
- /** The next batch of a removed connection's links. */
806
+ /** The next batch of a removed owner's links and pixels. */
750
807
  export const unlinkConnection = internalMutation({
751
- args: { connectionId: v.id("metaConnections") },
808
+ args: {
809
+ connectionId: v.optional(v.id("metaConnections")),
810
+ ownerKey: v.optional(v.string()),
811
+ /** The removal's time: the owner's pixels as they were then. */
812
+ before: v.optional(v.number()),
813
+ /** The `_creationTime` of the last owner pixel already walked. */
814
+ after: v.optional(v.number()),
815
+ },
752
816
  returns: v.null(),
753
817
  handler: async (ctx, args) => {
754
- await unlinkConnectionBatch(ctx, args.connectionId);
818
+ await removeOwnerBatch(ctx, args);
755
819
  return null;
756
820
  },
757
821
  });
@@ -7,6 +7,7 @@ import {
7
7
  type QueryCtx,
8
8
  } from "./_generated/server.js";
9
9
  import { fail } from "./errors.js";
10
+ import { ownerKeyOf } from "./meta.js";
10
11
  import { enqueueColumnEvent, type MetaUserData } from "./metaCapi.js";
11
12
  import { cleanString } from "./sanitize.js";
12
13
  import {
@@ -139,10 +140,30 @@ export const setEventMap = mutation({
139
140
  siteId: v.id("sites"),
140
141
  columns: v.record(v.string(), v.union(metaColumnEventValidator, v.null())),
141
142
  sendLeadEvent: v.boolean(),
143
+ /**
144
+ * The owner saving the map. The map feeds the site's pixel, so whoever
145
+ * set the pixel decides it: with `ownerKey`, a pixel another owner (or
146
+ * the host) set is a `CONFLICT`. A site without a pixel takes anyone's.
147
+ */
148
+ ownerKey: v.optional(v.string()),
142
149
  },
143
150
  returns: v.null(),
144
151
  handler: async (ctx, args) => {
145
152
  await requireSite(ctx, args.siteId);
153
+ const pixel = await ctx.db
154
+ .query("sitePixels")
155
+ .withIndex("by_siteId", (range) => range.eq("siteId", args.siteId))
156
+ .unique();
157
+ if (
158
+ args.ownerKey !== undefined &&
159
+ pixel &&
160
+ pixel.setBy !== ownerKeyOf(args.ownerKey)
161
+ ) {
162
+ fail(
163
+ "CONFLICT",
164
+ "the site's pixel was set by another owner on this host; change its events there",
165
+ );
166
+ }
146
167
  const existing = await pipelineOf(ctx, args.siteId);
147
168
  const declared = new Set((existing?.columns ?? []).map((row) => row.key));
148
169
  for (const key of Object.keys(args.columns)) {
@@ -174,14 +195,11 @@ export const setEventMap = mutation({
174
195
  updatedAt: now,
175
196
  });
176
197
  }
177
- const pixel = await ctx.db
178
- .query("sitePixels")
179
- .withIndex("by_siteId", (range) => range.eq("siteId", args.siteId))
180
- .unique();
198
+ // `updatedAt` stays: it says when the pixel itself was set, which is what
199
+ // removing its owner compares against.
181
200
  if (pixel && pixel.sendLeadEvent !== args.sendLeadEvent) {
182
201
  await ctx.db.patch("sitePixels", pixel._id, {
183
202
  sendLeadEvent: args.sendLeadEvent,
184
- updatedAt: now,
185
203
  });
186
204
  }
187
205
  return null;
@@ -1,5 +1,5 @@
1
1
  // Generated by scripts/build-tracker.mjs. Do not edit.
2
- export const RASTRO_VERSION = "0.10.0";
2
+ export const RASTRO_VERSION = "0.10.1";
3
3
  export const TRACKER_SOURCE = "(()=>{const t=document.currentScript,e=t?.dataset.site,i=t?.dataset.endpoint||t?.src&&new URL(\"events\",t.src).href;if(!e||!i)return;const n=()=>crypto.randomUUID?.()||Math.random()+\"\",r=new URLSearchParams(location.search),s=r.get(\"ref\")?.slice(0,64);let o;for(const t of[\"source\",\"medium\",\"campaign\",\"term\",\"content\"]){const e=r.get(\"utm_\"+t)?.slice(0,64);e&&((o??={})[\"utm_\"+t]=e)}const a=\"gclid gbraid wbraid msclkid ttclid twclid li_fat_id ScCid rdt_cid dclid epik srsltid mc_cid mc_eid _hsenc igsh igshid fbclid\".split(\" \").filter(t=>r.has(t)).slice(0,8);let c,d,l,h,f=t.dataset.visitor||\"\",p=Boolean(f);try{f||=localStorage._rv||=n()}catch{}try{d=sessionStorage,l=d._r,c=d._ri==f&&d._rt,h=s||d._a,h&&(d._a=h),o||=d._u&&JSON.parse(d._u),o&&(d._u=JSON.stringify(o))}catch{h=s}let v,g=0;const u=[];let m=document.referrer.split(\"/\",3).join(\"/\")||void 0;const _=t=>{const n=u.splice(0,50);if(!n.length)return;const r=()=>new Blob([JSON.stringify({siteId:e,events:n,sentAt:Date.now()})]);let s=r();for(;s.size>64e3&&n.length>1;)u.unshift(n.pop()),s=r();t&&navigator.sendBeacon(i,s)||fetch(i,{method:\"POST\",body:s,keepalive:1}).catch(()=>{}),u.length&&_(t)},y=(t,e,i)=>{const r=Date.now(),s=r-c;c=r,s<18e5||(l=n(),\"pageview\"!=t&&(S=\"\",w()));try{d._r=l,d._ri=f,d._rt=r}catch{}u.push({eventId:`${l}.${r.toString(36)}.${g}`,sessionId:l,visitorId:f||l,type:t,name:e,path:location.pathname.slice(0,256),referrer:m,timestamp:r,sequence:g++,affiliateSlug:h,...i}),clearTimeout(v),v=setTimeout(_,1200)};let S;const w=()=>{const t=location.pathname;t!=S&&(S=t,y(\"pageview\",void 0,{properties:o,clid:a.length?a:void 0}))};window.rastro=(e,i,r)=>{if(\"context\"==e)return{sessionId:l,visitorId:f||l,identified:p};if(\"identify\"==e||\"reset\"==e){if(\"identify\"==e&&(!i||i.length>128||!/^[A-Za-z0-9][A-Za-z0-9_.:-]*$/.test(i)))return;if(\"identify\"==e&&i==f)return;_();const r=\"reset\"==e||p;if(p=\"identify\"==e,f=\"identify\"==e?i:n(),t.dataset.visitor=\"identify\"==e?f:\"\",r){h=void 0,o=void 0,m=void 0,a.length=0;try{\"reset\"==e&&(localStorage._rv=f),d._a=\"\",d._u=\"\"}catch{}}c=0,g=0,S=\"\",w()}\"event\"==e&&y(\"custom\",`${i||\"event\"}`.slice(0,80),r&&JSON.stringify(r).length>2e4?void 0:{properties:r})},document.addEventListener(\"click\",t=>{const e=t.target?.closest(\"a,button,[data-rastro-event]\");if(!e)return;const i=e.dataset.rastroEvent,n=e.href,r=n&&new URL(n),s=/^https?:$/.test(r?.protocol),o=s&&r.origin!=location.origin;y(i?\"custom\":o?\"outbound\":\"click\",i,{target:(e.dataset.rastroLabel||e.innerText||e.tagName).slice(0,64),href:s?((o?r.origin:\"\")+r.pathname).slice(0,256):void 0})},1);for(const t of[\"pushState\",\"replaceState\"]){const e=history[t];history[t]=(...t)=>{e.apply(history,t),w()}}addEventListener(\"popstate\",w);let b=0;const I=()=>{y(\"heartbeat\"),_()},L=()=>{b&&(clearInterval(b),b=0,y(\"leave\"),_(1))},E=()=>{document.hidden?L():b||(I(),b=setInterval(I,2e4))};addEventListener(\"pagehide\",L),addEventListener(\"pageshow\",E),document.addEventListener(\"visibilitychange\",E),b=setInterval(I,2e4),w(),E()})();";
4
4
  export const TRACKER_GZIP_BASE64 = "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";
5
5
  export const TRACKER_RAW_BYTES = 2999;
@@ -1 +0,0 @@
1
- {"version":3,"file":"overlay.d.ts","sourceRoot":"","sources":["../../../src/ui/integrations/overlay.ts"],"names":[],"mappings":"AAAA,OAAO,EAA+B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAKpE;;;;GAIG;AACH,wBAAgB,QAAQ,CACtB,GAAG,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,EAClC,OAAO,EAAE,MAAM,IAAI,EACnB,OAAO,CAAC,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,QA2CxC;AAED,yEAAyE;AACzE,wBAAgB,UAAU,CACxB,IAAI,EAAE,OAAO,EACb,IAAI,EAAE,aAAa,CAAC,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC,EAClD,OAAO,EAAE,MAAM,IAAI,QAsBpB"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"overlay.js","sourceRoot":"","sources":["../../../src/ui/integrations/overlay.ts"],"names":[],"mappings":"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"}