@iann29/rastro 0.11.1 → 0.11.3

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 (46) hide show
  1. package/dist/client/index.d.ts +3 -9
  2. package/dist/client/index.d.ts.map +1 -1
  3. package/dist/client/index.js +1 -0
  4. package/dist/client/index.js.map +1 -1
  5. package/dist/client/metaHashes.d.ts +50 -0
  6. package/dist/client/metaHashes.d.ts.map +1 -0
  7. package/dist/client/metaHashes.js +116 -0
  8. package/dist/client/metaHashes.js.map +1 -0
  9. package/dist/component/_generated/component.d.ts +1 -0
  10. package/dist/component/_generated/component.d.ts.map +1 -1
  11. package/dist/component/leads.d.ts +1 -0
  12. package/dist/component/leads.d.ts.map +1 -1
  13. package/dist/component/leads.js +11 -0
  14. package/dist/component/leads.js.map +1 -1
  15. package/dist/component/metaCapi.d.ts +10 -3
  16. package/dist/component/metaCapi.d.ts.map +1 -1
  17. package/dist/component/metaCapi.js +45 -16
  18. package/dist/component/metaCapi.js.map +1 -1
  19. package/dist/component/metaGraph.d.ts +6 -0
  20. package/dist/component/metaGraph.d.ts.map +1 -1
  21. package/dist/component/metaGraph.js.map +1 -1
  22. package/dist/component/metaLeads.d.ts.map +1 -1
  23. package/dist/component/metaLeads.js +7 -2
  24. package/dist/component/metaLeads.js.map +1 -1
  25. package/dist/component/schema.d.ts +20 -2
  26. package/dist/component/schema.d.ts.map +1 -1
  27. package/dist/component/validators.d.ts +18 -1
  28. package/dist/component/validators.d.ts.map +1 -1
  29. package/dist/component/validators.js +11 -0
  30. package/dist/component/validators.js.map +1 -1
  31. package/dist/tracker/generated.d.ts +5 -5
  32. package/dist/tracker/generated.d.ts.map +1 -1
  33. package/dist/tracker/generated.js +5 -5
  34. package/dist/tracker/generated.js.map +1 -1
  35. package/dist/ui/forms/FormsView.d.ts.map +1 -1
  36. package/dist/ui/forms/FormsView.js +3 -1
  37. package/dist/ui/forms/FormsView.js.map +1 -1
  38. package/docs/meta-ads.md +35 -15
  39. package/package.json +1 -1
  40. package/src/component/_generated/component.ts +1 -0
  41. package/src/component/leads.ts +11 -0
  42. package/src/component/metaCapi.ts +48 -15
  43. package/src/component/metaGraph.ts +11 -1
  44. package/src/component/metaLeads.ts +8 -2
  45. package/src/component/validators.ts +11 -0
  46. package/src/tracker/generated.ts +5 -5
@@ -75,38 +75,65 @@ const digestOf = (value: unknown): string | null => {
75
75
  function ignored(): null {
76
76
  // Never the value itself: it may be a plain phone number.
77
77
  console.warn(
78
- "[rastro] meta ignored: expected { ph: SHA-256 hex digests, externalId?: a SHA-256 hex digest }",
78
+ "[rastro] meta ignored: expected { ph, em?, fn?, ln?, ct?, st?, zp?: SHA-256 hex digests, externalId?: a SHA-256 hex digest }",
79
79
  );
80
80
  return null;
81
81
  }
82
82
 
83
+ /** Meta's other customer information fields, each a list of digests. */
84
+ const USER_FIELDS = ["em", "fn", "ln", "ct", "st", "zp"] as const;
85
+ type UserField = (typeof USER_FIELDS)[number];
86
+ /** Values a field may carry (variants: with and without accents…). */
87
+ const MAX_FIELD_VALUES = 4;
88
+
89
+ /** A list of digests, deduplicated, without the hash of nothing; or null. */
90
+ function digestList(value: unknown, max: number): string[] | null {
91
+ const items = value ?? [];
92
+ if (!Array.isArray(items) || items.length > max) return null;
93
+ const out: string[] = [];
94
+ for (const item of items) {
95
+ const hash = digestOf(item);
96
+ if (hash === null) return null;
97
+ if (hash !== EMPTY_SHA256 && !out.includes(hash)) out.push(hash);
98
+ }
99
+ return out;
100
+ }
101
+
83
102
  /**
84
103
  * The host's hashes, checked, or null when there is nothing to send with.
85
104
  * Never throws and never echoes what it got: anything but SHA-256 hex digests
86
- * in the documented shape (a plain phone number, a wrong type, more than
87
- * MAX_PHONES phones) drops the whole `meta`, so the lead's own write goes on
88
- * without the Conversions API. The hash of an empty string is left out.
105
+ * in the documented shape (a plain phone number or e-mail, a wrong type, more
106
+ * than MAX_PHONES phones or MAX_FIELD_VALUES values of another field) drops
107
+ * the whole `meta`, so the lead's own write goes on without the Conversions
108
+ * API. The hash of an empty string is left out.
89
109
  */
90
110
  export function parseMetaUserData(value: unknown): MetaUserData | null {
91
111
  if (value === undefined || value === null) return null;
92
112
  if (typeof value !== "object" || Array.isArray(value)) return ignored();
93
- const fields = value as { ph?: unknown; externalId?: unknown };
94
- const phones = fields.ph ?? [];
95
- if (!Array.isArray(phones) || phones.length > MAX_PHONES) return ignored();
96
- const ph: string[] = [];
97
- for (const item of phones) {
98
- const hash = digestOf(item);
99
- if (hash === null) return ignored();
100
- if (hash !== EMPTY_SHA256 && !ph.includes(hash)) ph.push(hash);
101
- }
113
+ const fields = value as Record<string, unknown>;
114
+ const ph = digestList(fields.ph, MAX_PHONES);
115
+ if (ph === null) return ignored();
102
116
  let externalId: string | undefined;
103
117
  if (fields.externalId !== undefined) {
104
118
  const hash = digestOf(fields.externalId);
105
119
  if (hash === null) return ignored();
106
120
  if (hash !== EMPTY_SHA256) externalId = hash;
107
121
  }
108
- if (ph.length === 0 && externalId === undefined) return null;
109
- return { ph, ...(externalId ? { externalId } : {}) };
122
+ const more: Partial<Record<UserField, string[]>> = {};
123
+ for (const field of USER_FIELDS) {
124
+ if (fields[field] === undefined) continue;
125
+ const hashes = digestList(fields[field], MAX_FIELD_VALUES);
126
+ if (hashes === null) return ignored();
127
+ if (hashes.length > 0) more[field] = hashes;
128
+ }
129
+ if (
130
+ ph.length === 0 &&
131
+ externalId === undefined &&
132
+ Object.keys(more).length === 0
133
+ ) {
134
+ return null;
135
+ }
136
+ return { ph, ...(externalId ? { externalId } : {}), ...more };
110
137
  }
111
138
 
112
139
  // ---------------------------------------------------------------------------
@@ -542,6 +569,12 @@ export async function conversionEvent(
542
569
  user_data: {
543
570
  ...(userData.ph.length > 0 ? { ph: userData.ph } : {}),
544
571
  ...(userData.externalId ? { external_id: [userData.externalId] } : {}),
572
+ ...Object.fromEntries(
573
+ USER_FIELDS.flatMap((field) => {
574
+ const hashes = userData[field];
575
+ return hashes && hashes.length > 0 ? [[field, hashes]] : [];
576
+ }),
577
+ ),
545
578
  // Every site Rastro serves today sells in Brazil.
546
579
  country: [await sha256Hex("br")],
547
580
  },
@@ -267,7 +267,17 @@ export interface ConversionEvent {
267
267
  event_time: number;
268
268
  event_id: string;
269
269
  action_source: "chat";
270
- user_data: { ph?: string[]; external_id?: string[]; country: string[] };
270
+ user_data: {
271
+ ph?: string[];
272
+ external_id?: string[];
273
+ em?: string[];
274
+ fn?: string[];
275
+ ln?: string[];
276
+ ct?: string[];
277
+ st?: string[];
278
+ zp?: string[];
279
+ country: string[];
280
+ };
271
281
  custom_data?: { value: number; currency: string };
272
282
  }
273
283
 
@@ -386,8 +386,14 @@ export const savePages = internalMutation({
386
386
  continue;
387
387
  }
388
388
  // A fresh token resumes a Page a dead token (or a missing grant) had
389
- // stopped.
390
- if (link.nextReconcileAt === PAUSED_AT) {
389
+ // stopped, and a fresh listing retries at once a Page Meta refused for
390
+ // a permission: the login that just granted it (`pages_manage_ads`…)
391
+ // should not wait out PERMISSION_RETRY_MS. A run in flight keeps its
392
+ // lease.
393
+ const refused =
394
+ link.runId === undefined &&
395
+ pageErrorCode(link.lastError) === "META_PERMISSION_MISSING";
396
+ if (link.nextReconcileAt === PAUSED_AT || refused) {
391
397
  await ctx.db.patch("sitePages", link._id, {
392
398
  lastError: undefined,
393
399
  failures: 0,
@@ -805,6 +805,17 @@ export const metaConversionEventNameValidator = v.union(
805
805
  export const metaUserDataValidator = v.object({
806
806
  ph: v.array(v.string()),
807
807
  externalId: v.optional(v.string()),
808
+ /**
809
+ * The rest of Meta's customer information, each a list of SHA-256 hex
810
+ * digests of values normalized as Meta asks (`metaUserHashes` in the
811
+ * client does it): e-mail, first and last name, city, state, zip.
812
+ */
813
+ em: v.optional(v.array(v.string())),
814
+ fn: v.optional(v.array(v.string())),
815
+ ln: v.optional(v.array(v.string())),
816
+ ct: v.optional(v.array(v.string())),
817
+ st: v.optional(v.array(v.string())),
818
+ zp: v.optional(v.array(v.string())),
808
819
  });
809
820
 
810
821
  /** A conversion sent (or queued) to the site's Meta pixel. No user data. */
@@ -1,12 +1,12 @@
1
1
  // Generated by scripts/build-tracker.mjs. Do not edit.
2
- export const RASTRO_VERSION = "0.11.1";
2
+ export const RASTRO_VERSION = "0.11.3";
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
- export const TRACKER_GZIP_BASE64 = "H4sIAAAAAAACA31WW3PbuBn9KzYnowFqmLFzm5Qqotl08+COu7tTJS/1eBWIBEU0FMECH+VqRf73HvAixXZmXwgQ1+9yzvnAGJcfDqmtPJ2RzGzabHVFcdo4h3aZOlOT0JIWcaZIeU2xN6SF+X5EV1ltTUVti0Hv0tms0g9nX/51yyK9wyk+EhTGeVw4nc9Nzs51254b7jQ1rpoPt1cymJK6fU02dqrK7PbLl5ufFzHjbftPRcU4yPhFFAknxzuWWrm0+E05tfWstKkiY6vY96NceOnijSYW4eKIw7rSpJpdiXdv+LzUdGbnuXVsdP/M5neRt41LdSSirc5Ms0UnVdtamU2FLmnXj9iK4Fd0z8fI6emahrar6IKe3KRnM8bsYiEPHb+b1txLzbthu5LRJi1NdrZZO4XmYWi2Pi2/oSXqJ+mhb0qzyhWt0Fumf8fXZbRK0Wb9rK7NtzPvfEnhgLSfQaPRrAqvq/TMbHzRfzCUr8OmKPZ1aWD9WcTj3JTwkpH84OJCeUacH315PwQtFZkoRSFySUcM7AxwYV3bIje1/GhtqVXFcj4ntz/kbStDasollqiNjlduh6GKIQCK0uLQhVWZ9Np7ZG9cJUqZYaVI+8ZImc9moUeikL5t0VWiQGRDRyLXFkei38xm/1j++ktcK+d1mGwwNSxrZD/jyZlqY/I9s3yyAEd2wbed2MirEZGNvLvvHd6eiAEcaVDDTSF7GYnXPP4P4B/6QOrOIq7TCStJR3ZVsuk39ZF8e8V7HlRxqasNFY+p4HoqBIB/LO2a3T2x+hAoeJMlWgz0SiqBzNJPlPysSMeVfUBg+f2QLDCA8R7lcw/u/qE/vHujX4Oi480frue8iZsKeMiJVXFta8Z74mAbYZ3amY1CRsCpKvuoFUxkRni4mmtEDv3DVlNhsyT67dfl50isbbZPvPimda1Ks9PJdcfjPsqsF5uOi2a8fDZbAWCd2EsGlRHmpEVOnnwJxlym81Q64f92/V6/bVtWBvSIqAZOdkY/ROcStrKlBPywgw+4C2iRpRjgk/ctSTdhronrxhfs0AcR4fz64lB28YuDi8ku+2Cz1+94GNl0X8WITawrxQh29IHsUtC+1gmJSm01clJDqpKjEIW/MHHk0Ku377iYUJRsBZmt9gSJSeCd/m8Diupkc3EhVA4qGgRhWTabpBBxHBuELgWx3Gdssg2xHRc7sIam/5W4fnV1xbs+88sRTQ/ykcY/M21O53LZB4/Enp1CKgYoi0PtbK0dGe0TK4JgJGrM30Ilw6IORJo/GOjzA2QaULWSIZ/ChZsB9EEy/0eRhOoNWD/8SURNhpSY3OgsqbtAlGgc2YcDIDJOw+v+sMPTWXhybtrWHPH96j2Kzcvf7366/Le6/OPq8q/3p+4qTi7v//LiZUxIAjMAzkjE56cGAZpmV+DGhNOTLW1bh321fLQTMvnof2GSAN1n0vlkVZ6EKschTGMa7NTZTp0pCxCsgPaTIQjBU7mF7aIXSpzaK2EUTTzoUnkVVE9M7OmGsj2cBESkjSeLugeCILDjZPf1VBaugOhRdU8q5fiUgVf6zWIwOfkeS64D84/CqrLsUzj41njUVlSgCEhLv+HpcMQuniExKYdCu4jT0vqQskiJdUNkK3EX4nk5gO+yt/E+GkRWP1ZXI/Ux9sPy/mJRYTw8UMLb4vSEqYL8vPy9IKr9IpmQ4hYxPCGb2hLVRfrZzMXWmY2pzk8EGwbme2YWUwwTu4hA1LVtqixKJhchoYNfCXtq2q1a67JtdWwqBOUzKBR+SG1+AXP5968MEWxP/CK8NCZjgCF+4Y5M549U6EjdTlzzZ++goI1LgvzgveN0XapUD7/fPXoK5Mq6/R3dz09dyaBUFHivY1XX5Z6Nc4J4j67ueapRdPxw18NQtdbHInwzqBdgWED4aK0VRVyAgJ24HabWgHuvijeQGLdTJVtzgQOCmGF4p/v111Ao8WnYcQQd3kDg3OKW8WSNonLDwkYE/3jSjQB4g7b9wGYwC/th8y0XP572hYWMfuJ/hvLA/jWEnvZpoaqN7tf/yIgQO/EpVHaIz/8BGKXLCLcLAAA=";
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;
6
- export const TRACKER_GZIP_BYTES = 1562;
6
+ export const TRACKER_GZIP_BYTES = 1565;
7
7
  export const TRACKER_HASH = "6246dc584683303a";
8
8
  export const VITALS_SOURCE = "(()=>{const t=document.currentScript,e=t?.dataset.site,n=t?.dataset.endpoint||t?.src&&new URL(\"events\",t.src).href;if(!e||!n)return;const r=()=>crypto.randomUUID?.()||Math.random()+\"\";let s=t.dataset.visitor||\"\";try{s||=localStorage._rv||=r()}catch{}const o=Date.now();let a;try{a=sessionStorage._ri===s&&o-sessionStorage._rt<18e5&&sessionStorage._r||r(),sessionStorage._r=a,sessionStorage._ri=s,sessionStorage._rt=o}catch{a=r()}const i=s||a,c=location.pathname.slice(0,256),d={},h=[],l=(t,e,n)=>{try{const r=new PerformanceObserver(t=>e(t.getEntries()));r.observe({type:t,buffered:1,...n}),h.push({observer:r,handler:e})}catch{}},f=performance.getEntriesByType?.(\"navigation\")[0];f&&f.responseStart>0&&(d.TTFB=f.responseStart),l(\"paint\",t=>{for(const e of t)\"first-contentful-paint\"===e.name&&(d.FCP=e.startTime)}),l(\"largest-contentful-paint\",t=>{const e=t[t.length-1];e&&(d.LCP=e.startTime)});let m=0,u=0,v=0;l(\"layout-shift\",t=>{for(const e of t)e.hadRecentInput||(m&&e.startTime-v<1e3&&e.startTime-u<5e3?m+=e.value:(m=e.value,u=e.startTime),v=e.startTime,d.CLS=Math.max(d.CLS||0,1e3*m))});const g=[],p=new Set,S=t=>{for(const e of t)e.interactionId&&(p.add(e.interactionId),g.push(e.duration));if(!g.length)return;g.sort((t,e)=>e-t),g.length=Math.min(g.length,10);const e=performance.interactionCount||p.size;d.INP=g[Math.min(g.length-1,Math.floor(e/50))]};l(\"event\",S,{durationThreshold:40}),l(\"first-input\",S);let y=0;const b=()=>{if(y)return;for(const{observer:t,handler:e}of h)e(t.takeRecords()),t.disconnect();const t=Date.now(),r=Object.keys(d).map((e,n)=>({eventId:`${a}.${t.toString(36)}.v${n}`,sessionId:a,visitorId:i,type:\"vital\",name:e,value:Math.round(d[e]),path:c,timestamp:t,sequence:n}));if(!r.length)return;y=1;const s=new Blob([JSON.stringify({siteId:e,events:r,sentAt:t})]),o=navigator.sendBeacon?.bind(navigator);o&&o(n,s)||fetch(n,{method:\"POST\",body:s,keepalive:1}).catch(()=>{})};document.addEventListener(\"visibilitychange\",()=>{\"hidden\"===document.visibilityState&&b()}),addEventListener(\"pagehide\",b)})();";
9
- export const VITALS_GZIP_BASE64 = "H4sIAAAAAAACA3VVbW/bNhD+K6lQGORKc/a6FIMcJlj6AmTImqBOPwXBSosni6tEaiTlzpP033eU7MSt2w+GqSPv7rm7hw8JoeK8zazx4SQIZbOmAhN41jiH/8vM6TowEOGCKxmkh8C9DsDMoQWMqq02oevQ6F02mRj4cvLxwzVJYINRfMJCtFNeOMgXOifPoOueGeogNM4sxuxORCiZ29bBcieNstXHj1dvLjihXfenDMXOSOiLJFmUEE68CI8YNhpxWdd1uBfctvVdJ0qbyXKJVrkG/pfboMkR2mcyZEXbj1mteCMDcGO/EDoElYO7FB6819Y8uWshhJ9M7PRoJ5zNf4PTyeRoo+swHzsyC8m+E90fG4OwO7RyRD5AxqNdJ1k21BfQgdfYHSMr4L7UGZAZ++X0FWVKtD0rxP0DKwXBITITRx2r2zc8jukWXG5dJU0GNysPbgOOBHEOJPA1hLcmOA2eUEoXjtvxAGnDtoY0sFWT5+BApXPGOTc9ZQWvG1+QdnfSpY4VOLUSV9A/tr5nuaif8h4kutzeYWiceWLkRq+H8hJ6P3tY5JNJzh34GrHDMkgXzmeTCVH87u7dpfhmi7KSJLVETiL1sGjMRMai4cTmJ4EmuXY+TNEWkKB5U07H0zhjJAO2cgj97vUtfvoY8U5XQPshbindGr7nPKTapRHhPvASzDoU0/nDYox3fRRvoFwlZqzB30bMFkP8rW3C1Bc6/xF84IVUHyDD9FembvDmkWoyOQg93ZzN4eXXpubsFF5eVC8QwkaWDaSk2i8x/SEuRHLwyRR/fb0UwxWs5L9k+Oy6GcMMP1U0VjGCW0eu1QOrlhDYUvwAO/YKnMzibK8UNqbmUinyjZ2y9cgl4KpxAxGQg1E71ru+7uVjzb11gUSKI8FhGqLreGQHWhuyt7D5bA8XvuLgQfLXtoliVqPU/QcLxa/e34r1/VGo6ZwNtry0WCP8fDqj9KGPExxUL2FL1u6h36Hy+cKWKv11NrJoJKCO08OTIxG2SIAR22oQwxbL3e7LfGzk0+UKB5cLe1vQeGuD/AxIDetUvLaovEp79DOQBbIvPRyoHnPiZvU37vLPsPVEURxyTcgoF6QdarlS6afnrez58xYT2CXeVbMmL1/Rnm+et6b/tNcuPCjZTotxrdmgFMlGB1kmLF6sFNjIvlHSsdWKqHt4oCyqWJqxgJRD7lU1lufhnwZwOilqyzh8983wt2K+q8kPxLss7Yrc/7G8eY8Ejih1viVtfLMQDrDxPUJV8vj/e0hDTzGzFTu1sY7jhroEiTEv+EojuMcturAo/8Qwjw9SDqhkuG4rCIVVaXJ7s7xL2MqqberZZ4BalnoD6bynfFA9MgwUNXDx+Mgi699GPNfao5Cg7iaxcytd6rDNcLJrSNjglRRaKTBRnR6dn46i4gXUlxWJ+nQcs8a3BP0x1goPIAX+B8Hlft/zBwAA";
9
+ export const VITALS_GZIP_BASE64 = "H4sIAAAAAAACA3VVbW/bNhD+K6lQCORKc/ayFINcJlj6AnjImqBOPwXBSosniatEauTJnSbpvw+i7MSJ22/SkXf33N1zDwmh4rxLrfF4gkLZtKnAIE8b58DgOnW6RgYCL7iSKD0g9xqBmUMLGFVbbbDv8YJ7l8axgW8nnz9dkQi2YNBHDEc75YWDbKkz8gL6/oWhDrBxZjlld2KEkrq2RsudNMpWnz+v3l1wQvv+T4nFzkjoqyhaloAnXuADhq32Gq3r+yhaoms73/eitKks12idzIH/5bZ9LxyhQyoxLbphymrFO4nAjf1GaAgqg7sUHrzX1jy6ayGEj2M7OzrBN4vf4CyOjw763hHKjsxCsu9E98dGFHaHVk7IA2QtfN9Llob6UFvDa4mFkRVwX+oUyJz9cvaaMiW6gRXi7p6VgiADZsZRj9XtGz6O6QZcZl0lTQrXGw9uC46gOAeCPAd8b9Bp8IRSunTcThdIh20NCbJNk2XgQCULxjk3A2UFrxtfkG530yWOFdKoElwCw0PrB5aJ+jHvQaLL9rat4YKTyMitzkN5Eb2b3y+zOM64A19b42GN0uH5PI6J4re3Hy7FsyPKShLVUhuMGIrzLrOOTEXDic1OkEaZdh5nqTUIBrOmnE23hRDAx1aG0B/e3gjgfox4qyugQ4hbSpfD95xDql0agXfISzA5FrPF/XKKd3UUL1CuEnPWiDnbivkyxG9tgzNf6OxH8IEXUn2CFAyuTN1g35Mqjg9Cz7ZvFnD61NS8OYPTi+qVAL6VZQMJqfafrHmCi20Pf5nib6/WIqxgJf8l4bfv52wBpz9VdKxiApePXKsDq9aAbC1+gF0bBCfTcbYrFcek5lIp8sxOWT5xCbhqXCACpUE78l1f9/KRc28dkpHiVJzDDEfX6coOtDZkb2GL+R4uPOHgQfK3thnFrOZe/wdLxVcfb0R+dxRqtmDBlpXWOgI/n80pvR/GCQbVi9iadXvot4UDX9hSJb/OJxZNBNTj9CK2nojQivkO2yaIYacz0u7LfGjk43LhwXLZ7KSg49ai/AqfILVOjWvLkCvtU2sMpEj2peOB6jEnrjd/Q4r8K7SeKMorWRMyyQXpQi0rlXx52cmBv+yQo12j0yYnp6/pwLcvOzN82WvXSiWS7bR4pRLNglJEW42yjNi4WAmwiX2TpNvGKKLu4J6yUcWSlKGuwKOs6gSZh38aMCkkZtgN3z0bfisWu5p8IN5laTfk7o/19UfuA0qdtaQb36yVSoBN71HimAeDv2OCA72nzIqd2ljHPRh1CTK15oJvtFHk4YgubRxbYpinfZ8BpgUxrKsAC6uS6OZ6fRuxjVVt4tlXgFqWegvJYqA8qB4JAx3osHx4ZKVS70c8V9ojGHAkGju30aXGNi2kySFiwSsqtFJgRnV6cH68ukaJEMcbMurTccxa5lBoBRHb0IESuvwfweV+3/MHAAA=";
10
10
  export const VITALS_RAW_BYTES = 2035;
11
- export const VITALS_GZIP_BYTES = 1098;
11
+ export const VITALS_GZIP_BYTES = 1097;
12
12
  export const VITALS_HASH = "3dd7a68d5212c1f8";