@iann29/rastro 0.10.9 → 0.11.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 (178) hide show
  1. package/README.md +8 -0
  2. package/agent/integration.md +45 -0
  3. package/agent/manifest.json +4 -4
  4. package/dist/client/federation.d.ts +82 -9
  5. package/dist/client/federation.d.ts.map +1 -1
  6. package/dist/client/federation.js +40 -2
  7. package/dist/client/federation.js.map +1 -1
  8. package/dist/client/index.d.ts +464 -8
  9. package/dist/client/index.d.ts.map +1 -1
  10. package/dist/client/index.js +259 -7
  11. package/dist/client/index.js.map +1 -1
  12. package/dist/component/_generated/api.d.ts +10 -0
  13. package/dist/component/_generated/api.d.ts.map +1 -1
  14. package/dist/component/_generated/api.js.map +1 -1
  15. package/dist/component/_generated/component.d.ts +273 -21
  16. package/dist/component/_generated/component.d.ts.map +1 -1
  17. package/dist/component/_generated/server.d.ts +2 -0
  18. package/dist/component/_generated/server.d.ts.map +1 -1
  19. package/dist/component/_generated/server.js.map +1 -1
  20. package/dist/component/constants.d.ts +31 -0
  21. package/dist/component/constants.d.ts.map +1 -1
  22. package/dist/component/constants.js +31 -0
  23. package/dist/component/constants.js.map +1 -1
  24. package/dist/component/convex.config.d.ts +2 -0
  25. package/dist/component/convex.config.js +7 -0
  26. package/dist/component/convex.config.js.map +1 -1
  27. package/dist/component/errors.d.ts +1 -1
  28. package/dist/component/errors.d.ts.map +1 -1
  29. package/dist/component/errors.js.map +1 -1
  30. package/dist/component/http.d.ts.map +1 -1
  31. package/dist/component/http.js +64 -0
  32. package/dist/component/http.js.map +1 -1
  33. package/dist/component/leadAdsValidators.d.ts +1092 -0
  34. package/dist/component/leadAdsValidators.d.ts.map +1 -0
  35. package/dist/component/leadAdsValidators.js +304 -0
  36. package/dist/component/leadAdsValidators.js.map +1 -0
  37. package/dist/component/leadFormRules.d.ts +60 -0
  38. package/dist/component/leadFormRules.d.ts.map +1 -0
  39. package/dist/component/leadFormRules.js +140 -0
  40. package/dist/component/leadFormRules.js.map +1 -0
  41. package/dist/component/leadFormStore.d.ts +16 -0
  42. package/dist/component/leadFormStore.d.ts.map +1 -0
  43. package/dist/component/leadFormStore.js +92 -0
  44. package/dist/component/leadFormStore.js.map +1 -0
  45. package/dist/component/leadgenToken.d.ts +56 -0
  46. package/dist/component/leadgenToken.d.ts.map +1 -0
  47. package/dist/component/leadgenToken.js +262 -0
  48. package/dist/component/leadgenToken.js.map +1 -0
  49. package/dist/component/leads.d.ts +76 -7
  50. package/dist/component/leads.d.ts.map +1 -1
  51. package/dist/component/leads.js +112 -78
  52. package/dist/component/leads.js.map +1 -1
  53. package/dist/component/meta.d.ts.map +1 -1
  54. package/dist/component/meta.js +21 -1
  55. package/dist/component/meta.js.map +1 -1
  56. package/dist/component/metaFake.d.ts +44 -0
  57. package/dist/component/metaFake.d.ts.map +1 -1
  58. package/dist/component/metaFake.js +400 -1
  59. package/dist/component/metaFake.js.map +1 -1
  60. package/dist/component/metaGraph.d.ts +91 -0
  61. package/dist/component/metaGraph.d.ts.map +1 -1
  62. package/dist/component/metaGraph.js +217 -0
  63. package/dist/component/metaGraph.js.map +1 -1
  64. package/dist/component/metaLeads.d.ts +681 -0
  65. package/dist/component/metaLeads.d.ts.map +1 -0
  66. package/dist/component/metaLeads.js +2634 -0
  67. package/dist/component/metaLeads.js.map +1 -0
  68. package/dist/component/schema.d.ts +414 -5
  69. package/dist/component/schema.d.ts.map +1 -1
  70. package/dist/component/schema.js +169 -1
  71. package/dist/component/schema.js.map +1 -1
  72. package/dist/component/validators.d.ts +235 -11
  73. package/dist/component/validators.d.ts.map +1 -1
  74. package/dist/component/validators.js +14 -1
  75. package/dist/component/validators.js.map +1 -1
  76. package/dist/tracker/generated.d.ts +1 -1
  77. package/dist/tracker/generated.js +1 -1
  78. package/dist/ui/campaigns/CampaignsView.d.ts +5 -1
  79. package/dist/ui/campaigns/CampaignsView.d.ts.map +1 -1
  80. package/dist/ui/campaigns/CampaignsView.js.map +1 -1
  81. package/dist/ui/campaigns/Drawer.d.ts.map +1 -1
  82. package/dist/ui/campaigns/Drawer.js +8 -26
  83. package/dist/ui/campaigns/Drawer.js.map +1 -1
  84. package/dist/ui/campaigns/labels.d.ts +29 -1
  85. package/dist/ui/campaigns/labels.d.ts.map +1 -1
  86. package/dist/ui/campaigns/labels.js +77 -2
  87. package/dist/ui/campaigns/labels.js.map +1 -1
  88. package/dist/ui/campaigns/model.js +2 -2
  89. package/dist/ui/campaigns/model.js.map +1 -1
  90. package/dist/ui/forms/FirstContact.d.ts +19 -0
  91. package/dist/ui/forms/FirstContact.d.ts.map +1 -0
  92. package/dist/ui/forms/FirstContact.js +81 -0
  93. package/dist/ui/forms/FirstContact.js.map +1 -0
  94. package/dist/ui/forms/FormLead.d.ts +28 -0
  95. package/dist/ui/forms/FormLead.d.ts.map +1 -0
  96. package/dist/ui/forms/FormLead.js +199 -0
  97. package/dist/ui/forms/FormLead.js.map +1 -0
  98. package/dist/ui/forms/FormRulesDrawer.d.ts +49 -0
  99. package/dist/ui/forms/FormRulesDrawer.d.ts.map +1 -0
  100. package/dist/ui/forms/FormRulesDrawer.js +149 -0
  101. package/dist/ui/forms/FormRulesDrawer.js.map +1 -0
  102. package/dist/ui/forms/FormsView.d.ts +10 -0
  103. package/dist/ui/forms/FormsView.d.ts.map +1 -0
  104. package/dist/ui/forms/FormsView.js +215 -0
  105. package/dist/ui/forms/FormsView.js.map +1 -0
  106. package/dist/ui/forms/Icons.d.ts +46 -0
  107. package/dist/ui/forms/Icons.d.ts.map +1 -0
  108. package/dist/ui/forms/Icons.js +45 -0
  109. package/dist/ui/forms/Icons.js.map +1 -0
  110. package/dist/ui/forms/RuleRow.d.ts +37 -0
  111. package/dist/ui/forms/RuleRow.d.ts.map +1 -0
  112. package/dist/ui/forms/RuleRow.js +80 -0
  113. package/dist/ui/forms/RuleRow.js.map +1 -0
  114. package/dist/ui/forms/WhatsAppButtonGuide.d.ts +33 -0
  115. package/dist/ui/forms/WhatsAppButtonGuide.d.ts.map +1 -0
  116. package/dist/ui/forms/WhatsAppButtonGuide.js +90 -0
  117. package/dist/ui/forms/WhatsAppButtonGuide.js.map +1 -0
  118. package/dist/ui/forms/index.d.ts +11 -0
  119. package/dist/ui/forms/index.d.ts.map +1 -0
  120. package/dist/ui/forms/index.js +7 -0
  121. package/dist/ui/forms/index.js.map +1 -0
  122. package/dist/ui/forms/journey.d.ts +19 -0
  123. package/dist/ui/forms/journey.d.ts.map +1 -0
  124. package/dist/ui/forms/journey.js +54 -0
  125. package/dist/ui/forms/journey.js.map +1 -0
  126. package/dist/ui/forms/model.d.ts +239 -0
  127. package/dist/ui/forms/model.d.ts.map +1 -0
  128. package/dist/ui/forms/model.js +556 -0
  129. package/dist/ui/forms/model.js.map +1 -0
  130. package/dist/ui/forms/sample.d.ts +36 -0
  131. package/dist/ui/forms/sample.d.ts.map +1 -0
  132. package/dist/ui/forms/sample.js +444 -0
  133. package/dist/ui/forms/sample.js.map +1 -0
  134. package/dist/ui/forms/types.d.ts +454 -0
  135. package/dist/ui/forms/types.d.ts.map +1 -0
  136. package/dist/ui/forms/types.js +2 -0
  137. package/dist/ui/forms/types.js.map +1 -0
  138. package/dist/ui/index.d.ts +2 -0
  139. package/dist/ui/index.d.ts.map +1 -1
  140. package/dist/ui/index.js +4 -0
  141. package/dist/ui/index.js.map +1 -1
  142. package/dist/ui/integrations/Overlay.d.ts +3 -1
  143. package/dist/ui/integrations/Overlay.d.ts.map +1 -1
  144. package/dist/ui/integrations/Overlay.js +2 -2
  145. package/dist/ui/integrations/Overlay.js.map +1 -1
  146. package/dist/ui/portfolio/PortfolioView.d.ts +4 -1
  147. package/dist/ui/portfolio/PortfolioView.d.ts.map +1 -1
  148. package/dist/ui/portfolio/PortfolioView.js.map +1 -1
  149. package/dist/ui/sample.d.ts +3 -1
  150. package/dist/ui/sample.d.ts.map +1 -1
  151. package/dist/ui/sample.js +2 -0
  152. package/dist/ui/sample.js.map +1 -1
  153. package/dist/ui/seed.d.ts +1 -1
  154. package/dist/ui/ui.css +2301 -0
  155. package/docs/federation.md +19 -0
  156. package/docs/meta-ads.md +713 -7
  157. package/docs/upgrading.md +70 -0
  158. package/llms.txt +1 -0
  159. package/package.json +1 -1
  160. package/src/component/_generated/api.ts +10 -0
  161. package/src/component/_generated/component.ts +289 -20
  162. package/src/component/_generated/server.ts +2 -0
  163. package/src/component/constants.ts +33 -0
  164. package/src/component/convex.config.ts +7 -0
  165. package/src/component/errors.ts +3 -1
  166. package/src/component/http.ts +75 -0
  167. package/src/component/leadAdsValidators.ts +365 -0
  168. package/src/component/leadFormRules.ts +202 -0
  169. package/src/component/leadFormStore.ts +129 -0
  170. package/src/component/leadgenToken.ts +348 -0
  171. package/src/component/leads.ts +136 -84
  172. package/src/component/meta.ts +21 -1
  173. package/src/component/metaFake.ts +485 -1
  174. package/src/component/metaGraph.ts +327 -0
  175. package/src/component/metaLeads.ts +3101 -0
  176. package/src/component/schema.ts +187 -1
  177. package/src/component/validators.ts +17 -1
  178. package/src/tracker/generated.ts +1 -1
@@ -28,6 +28,13 @@ import {
28
28
  reportRollupQueueFields,
29
29
  rollupFoldStateFields,
30
30
  } from "./rollupStore.js";
31
+ import {
32
+ firstContactValidator,
33
+ formChoiceAnswerValidator,
34
+ formLeadDecisionValidator,
35
+ formRuleValidator,
36
+ metaFormQuestionValidator,
37
+ } from "./leadAdsValidators.js";
31
38
 
32
39
  export default defineSchema({
33
40
  sites: defineTable(siteFieldsValidator)
@@ -424,7 +431,8 @@ export default defineSchema({
424
431
  leadDailyRollups: defineTable({
425
432
  siteId: v.id("sites"),
426
433
  dayStart: v.number(),
427
- dimension: v.union(v.literal("origin"), v.literal("ad")),
434
+ // `form` (since 0.11.0): a Meta instant form's leads, keyed by form id.
435
+ dimension: v.union(v.literal("origin"), v.literal("ad"), v.literal("form")),
428
436
  key: v.string(),
429
437
  leads: v.number(),
430
438
  qualified: v.number(),
@@ -765,4 +773,182 @@ export default defineSchema({
765
773
  Lead: v.number(),
766
774
  Schedule: v.number(),
767
775
  }).index("by_siteId_and_dayStart_and_shard", ["siteId", "dayStart", "shard"]),
776
+
777
+ // Lead Ads (metaLeads.ts, since 0.11.0). No table here ever holds a lead's
778
+ // name, phone, e-mail or free answer: those go from Meta to the host's
779
+ // handler in memory.
780
+
781
+ // A Facebook Page an owner's connection lists, with the Page's own token
782
+ // sealed with RASTRO_SECRETS_KEY (one row per connection and Page: two
783
+ // owners may list the same Page). No query returns the cipher.
784
+ metaPages: defineTable({
785
+ ownerKey: v.string(),
786
+ connectionId: v.id("metaConnections"),
787
+ pageId: v.string(),
788
+ name: v.string(),
789
+ tokenCipher: v.string(),
790
+ tokenIv: v.string(),
791
+ /** The Page tasks Meta granted the login: `ADVERTISE`, `MANAGE`… */
792
+ tasks: v.array(v.string()),
793
+ /** The login was granted `leads_retrieval` for this Page. */
794
+ leadsAllowed: v.boolean(),
795
+ /** False once a new listing left the Page out; kept while linked. */
796
+ listed: v.boolean(),
797
+ /** When Meta refused the Page's token; a new listing clears it. */
798
+ invalidSince: v.optional(v.number()),
799
+ createdAt: v.number(),
800
+ updatedAt: v.number(),
801
+ })
802
+ .index("by_connectionId_and_pageId", ["connectionId", "pageId"])
803
+ .index("by_pageId", ["pageId"]),
804
+
805
+ // A Page feeding a site's leads: subscribed to Meta's `leadgen` webhook and
806
+ // reconciled by the chain in metaLeads.ts. One Page feeds one site.
807
+ sitePages: defineTable({
808
+ siteId: v.id("sites"),
809
+ pageId: v.string(),
810
+ name: v.string(),
811
+ /** The owner whose connection (and Page token) the link reads with. */
812
+ ownerKey: v.string(),
813
+ connectionId: v.id("metaConnections"),
814
+ /** When Meta confirmed the `leadgen` subscription. */
815
+ subscribedAt: v.optional(v.number()),
816
+ /**
817
+ * When the reconciliation last made sure the app is still subscribed to
818
+ * the Page: the subscription is the Page's and the app's, shared by every
819
+ * host, so another host unlinking the Page may have taken it off.
820
+ */
821
+ subscriptionCheckedAt: v.optional(v.number()),
822
+ /** Leads created from here on are the link's (ms). */
823
+ reconcileFrom: v.number(),
824
+ nextReconcileAt: v.number(),
825
+ /** The run holding the link, as in the spend sync. */
826
+ runId: v.optional(v.string()),
827
+ lastReconcileAt: v.optional(v.number()),
828
+ lastLeadAt: v.optional(v.number()),
829
+ failures: v.optional(v.number()),
830
+ lastError: v.optional(v.string()),
831
+ createdAt: v.number(),
832
+ updatedAt: v.number(),
833
+ })
834
+ .index("by_siteId", ["siteId"])
835
+ .index("by_pageId", ["pageId"])
836
+ .index("by_connectionId", ["connectionId"])
837
+ .index("by_nextReconcileAt", ["nextReconcileAt"]),
838
+
839
+ // A Page's instant forms as Meta lists them.
840
+ metaForms: defineTable({
841
+ pageId: v.string(),
842
+ formId: v.string(),
843
+ name: v.string(),
844
+ status: v.string(),
845
+ questions: v.array(metaFormQuestionValidator),
846
+ /** The end screen's WhatsApp button; absent when Meta does not say. */
847
+ whatsappButton: v.optional(v.boolean()),
848
+ createdTime: v.optional(v.number()),
849
+ syncedAt: v.number(),
850
+ /**
851
+ * How far the reconciliation read this form's leads (Meta's seconds),
852
+ * for the link it read them for: a new link starts from its own time.
853
+ */
854
+ cursor: v.optional(
855
+ v.object({ linkId: v.id("sitePages"), sec: v.number() }),
856
+ ),
857
+ /** The last lead that came in from the form, for the site it fed. */
858
+ lastLead: v.optional(v.object({ siteId: v.id("sites"), at: v.number() })),
859
+ })
860
+ .index("by_pageId", ["pageId"])
861
+ .index("by_pageId_and_status", ["pageId", "status"])
862
+ .index("by_formId", ["formId"]),
863
+
864
+ // Where a site's form sends its leads. Editing affects the next leads only.
865
+ formRules: defineTable({
866
+ siteId: v.id("sites"),
867
+ formId: v.string(),
868
+ entryColumn: v.optional(v.string()),
869
+ rules: v.array(formRuleValidator),
870
+ /** Each rule's identity, for its monthly count (see leadFormRules.ts). */
871
+ signatures: v.array(v.string()),
872
+ firstContact: firstContactValidator,
873
+ whatsappButtonConfirmed: v.optional(v.boolean()),
874
+ /** The owner that saved them, when the host named one. */
875
+ setBy: v.optional(v.string()),
876
+ updatedAt: v.number(),
877
+ }).index("by_siteId_and_formId", ["siteId", "formId"]),
878
+
879
+ // One per ingested form lead: its origin, the choice answers and what the
880
+ // rules decided. `leadgenId` makes ingestion idempotent.
881
+ formLeads: defineTable({
882
+ siteId: v.id("sites"),
883
+ pageId: v.string(),
884
+ formId: v.string(),
885
+ leadgenId: v.string(),
886
+ leadId: v.id("leads"),
887
+ receivedAt: v.number(),
888
+ adId: v.optional(v.string()),
889
+ adsetId: v.optional(v.string()),
890
+ campaignId: v.optional(v.string()),
891
+ platform: v.optional(v.string()),
892
+ isOrganic: v.boolean(),
893
+ answers: v.array(formChoiceAnswerValidator),
894
+ decision: formLeadDecisionValidator,
895
+ rulePath: v.array(v.number()),
896
+ ruleIndex: v.optional(v.number()),
897
+ ruleSignature: v.optional(v.string()),
898
+ /** A discarded lead sent back to the funnel, and the reason it had. */
899
+ returned: v.optional(v.object({ at: v.number(), reason: v.string() })),
900
+ createdAt: v.number(),
901
+ })
902
+ .index("by_leadgenId", ["leadgenId"])
903
+ .index("by_leadId", ["leadId"])
904
+ .index("by_siteId_and_receivedAt", ["siteId", "receivedAt"])
905
+ .index("by_siteId_and_formId_and_receivedAt", [
906
+ "siteId",
907
+ "formId",
908
+ "receivedAt",
909
+ ])
910
+ .index("by_siteId_and_formId_and_ruleSignature_and_receivedAt", [
911
+ "siteId",
912
+ "formId",
913
+ "ruleSignature",
914
+ "receivedAt",
915
+ ]),
916
+
917
+ // A form lead the host removed (`leads.remove`): its leadgen id only, so
918
+ // no later read of the same lead (the webhook retried, the reconciliation
919
+ // reading the cursor's second, a new link's backfill) brings it back.
920
+ formLeadTombstones: defineTable({
921
+ leadgenId: v.string(),
922
+ removedAt: v.number(),
923
+ }).index("by_leadgenId", ["leadgenId"]),
924
+
925
+ // A form lead whose commit failed (the host's handler threw): its ids, how
926
+ // many times and the error's class or code, never its data. After
927
+ // `MAX_LEAD_ATTEMPTS` while later leads of the form come in, the
928
+ // reconciliation skips it (`skippedAt`) so they are not held behind it.
929
+ // Deleted when the lead comes in.
930
+ formLeadFailures: defineTable({
931
+ leadgenId: v.string(),
932
+ pageId: v.string(),
933
+ formId: v.string(),
934
+ attempts: v.number(),
935
+ lastCode: v.string(),
936
+ lastAt: v.number(),
937
+ skippedAt: v.optional(v.number()),
938
+ }).index("by_leadgenId", ["leadgenId"]),
939
+
940
+ // The host's form lead handler: a function handle the component calls with
941
+ // each lead (see `setFormLeadHandler`). One per deployment.
942
+ metaFormLeadHandler: defineTable({
943
+ key: v.literal("handler"),
944
+ handle: v.string(),
945
+ updatedAt: v.number(),
946
+ }).index("by_key", ["key"]),
947
+
948
+ // The single scheduler chain that reconciles every linked Page.
949
+ metaLeadsLoop: defineTable({
950
+ key: v.literal("loop"),
951
+ scheduledFor: v.number(),
952
+ jobId: v.id("_scheduled_functions"),
953
+ }).index("by_key", ["key"]),
768
954
  });
@@ -1,4 +1,5 @@
1
1
  import { v, type Infer } from "convex/values";
2
+ import { formLeadDetailValidator } from "./leadAdsValidators.js";
2
3
 
3
4
  export const personAttributeValueValidator = v.union(
4
5
  v.string(),
@@ -384,7 +385,14 @@ export const trackedLinkFieldsValidator = v.object({
384
385
  * behind it. Today the channel is WhatsApp; the stage follows the host's
385
386
  * pipeline as `lead` → `qualified` → `won`, or `lost`.
386
387
  */
387
- export const leadChannelValidator = v.literal("whatsapp");
388
+ /**
389
+ * Where the lead talks to the host: a WhatsApp conversation, or (since
390
+ * 0.11.0) a Meta instant form the lead filled in (`lead_form` origin).
391
+ */
392
+ export const leadChannelValidator = v.union(
393
+ v.literal("whatsapp"),
394
+ v.literal("form"),
395
+ );
388
396
  export const leadStageValidator = v.union(
389
397
  v.literal("lead"),
390
398
  v.literal("qualified"),
@@ -440,6 +448,8 @@ export const leadFieldsValidator = v.object({
440
448
  /** The host's board column the lead is in now (see `setPipeline`). */
441
449
  column: v.optional(v.string()),
442
450
  columnAt: v.optional(v.number()),
451
+ /** Since 0.11.0: the Meta instant form the lead filled in (metaLeads.ts). */
452
+ form: v.optional(v.object({ formId: v.string(), pageId: v.string() })),
443
453
  updatedAt: v.number(),
444
454
  });
445
455
 
@@ -847,6 +857,12 @@ export const leadJourneyValidator = v.union(
847
857
  }),
848
858
  ),
849
859
  visitorId: v.union(v.string(), v.null()),
860
+ /**
861
+ * Since 0.11.0, on a Meta instant form's lead: its choice answers, where
862
+ * it came from and the path the form's rules took. Null when the lead
863
+ * has no ingestion record left.
864
+ */
865
+ form: v.optional(v.union(formLeadDetailValidator, v.null())),
850
866
  events: v.array(
851
867
  v.object({
852
868
  type: leadEventTypeValidator,
@@ -1,5 +1,5 @@
1
1
  // Generated by scripts/build-tracker.mjs. Do not edit.
2
- export const RASTRO_VERSION = "0.10.9";
2
+ export const RASTRO_VERSION = "0.11.0";
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 = "H4sIAAAAAAACA31W23LbOBL9FRmVYgHrNiI7l8pSi6gmO3nwludSq+RlXR4FIpsiNhTAAZrSaET++xRIUYrt1LyQALqBbjTOOQDnQr0/ZM4GmpDKXdZs0JLMGu/R0iLzpiZARXOZa9IBSQZDCObbEbR57YyltqW5DD5LEou7yef/3nGGW7QUGFAcF7L0WMxMwS+wbS+M8EiNt7MhulUxlczva3LSa5u7zefPtz/OJRdt+5Om8jjIxSVj4NUxxgK1z8pftdebwCuXaTLOytCPCgjKyzUSZx4LJuYyVCZDPoW3r8WsQpq4WeE8P25/4op7FlzjM2TANpibZsOAZXpTa7O2DBih70ecJbTEHsSxcjiGaWizZJf0JBImCeduPleHTtyPPg8KRTdM14qts8rkk/XKa5NPdsNvE7Lqq8knRL2Rdv2vMstC09Lkk0X2b5NPfE7LzOSTvLdibb5Ogg8VxQWy3rLJlmjyybIMaLOJWYey/5h8UqziJCZDXRnibMKELExF6Dmp916WOnAS4rSXd0PRMsihghIKRScMbE0w5HzbMga1+uBchdryQszI7w9F26p4NNWCnNdrlEu/bVtluegyTVl56KJXrgKGYJw9ekGlcrn0kPU/o1SRJLFFUKrQtrlcaiiThMeGKgW4to2eTZL8Z/HLz7LWPmA0NgLc4Nao3hLIG7s2xZ47MWZQqtDFvW1hraZHRDbq/qHf8OZMDI8Feo9+LNlLBq+E/L8zNrZF226dySfjCktFJ3ZZ1fST+kq+mYqeB1ZWaNdUPqaC76kQAf6hcit+/yTrQ6TgbZ4iDPRKLQS09AOlP2pCad2Oi048DIcVlOeiR/ksyGD+xPdvX+OrJBkjv7+eiUY2NpSmIG5l7WoueuJwMaMksXpr1pqclwFt/gF15iw3EETbFkhZyQ0cNkily1P26y+LTwxWLt+nAb4i1royW0yvOyH7KvNebDoBzTF4kiw5iQ72ihMgmLMWeXXeS0zmKptlykP41/U7fNO2vIroAVbrNW4N7tiFoiThC8UY7LgQA+4iWlQFA3yK/k/Kj5hrZN2Ekh/6It7m6ZcXh6qTLw5eklv0xeav3oo4su6+wBGbt3lawRHst3latG0FtK8xJbB6gylCralMT0IUe9Fw4tDNm7cCRhSlGyCzwUB6U6ceAv7eoM0wXV9egi4KUxlNuKiadVqClNJ0ArIKtf9kNuga4lsBWxWQxv4Srm+mU9H1J784ommnHmn8s9RmdKEWffEI9vxcUhigDIfauxo9GQypgygYqT6e31yng1MnRDfbGZu7nfQ6kHeKIxjwMbIp+CCZfxBTCo9YP/xNRU2OlkxhME/rLhKFHUf2cYG2ZR4DDosdnlqThF+YtjUnfN+8a9uLl7/d/3D1P3315/Tqnw/n5lKmVw//ePFSEgbiRoiRiM9XjQI0WpdcnKh6zqVt6zivVo9mQvG4PzdphO4z6XziVaTxlhOHUh2PwY2NzdgYT0FNe7SfE0kS/lRuVSGgF0rGoFdCxkYedJmaRtWDkT3dcG0PK+05y5pAbsPgy4uDadujsftyvhamAvxRdc8q5cV4Ajf4ej6knH6LJd+JDk7CqvP8Y1z4zgRCi56zrDLZVwZnBUVFkrRfI81lVrkQj4xpWDVEzsJ9rOfVAL6rPscHNogsPlZXo/BU+8G9DwxWYf9AiW+L8xPGRvl5+VtJVId5OiLFz2XtHbnMVQKcCknipfNmbezFmWDDwGzPzXysYermzDW0co3NWTpu0cBh2FfKn6Z2p1dYtS1KYy36T/gHxQ7p9c96g+LbVwbE3NMwjy+NMZmUMXHpT0wXj1ToRN0OrsWzd1DUxgVpik8hj3WlMxy63zx6ShPI+f09PczOTcWllBR5j1LXdbXnRxuQ6NHVPT/q2tVhiLUbbq3V6RK+HdRrz1mJ2tMKNTEBSy46uBtMqyThvSreWkK/1RVfCVipaRSzCvUWe/9rITr4OMw4ga40eY52fsdFumpbfsvjxIB0WukWbvB11Lbv5KzXWJocGdwJ+L45lG7H4KP4O5RH9q9MZWifldqusff/XhKxdvAx3uxczP4CGKXLCLcLAAA=";
5
5
  export const TRACKER_RAW_BYTES = 2999;