@sendermaster/react 0.0.0-stage → 0.2.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.
- package/CHANGELOG.md +7 -0
- package/README.md +71 -2
- package/dist/browser.cjs +1 -0
- package/dist/browser.d.ts +1 -0
- package/dist/browser.js +1 -0
- package/dist/index.cjs +2 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/dist/types/browser/src/consent.d.ts +15 -0
- package/dist/types/browser/src/core.d.ts +53 -0
- package/dist/types/browser/src/index.d.ts +56 -0
- package/dist/types/event-contracts/src/index.d.ts +250 -0
- package/dist/types/react/src/browser.d.ts +1 -0
- package/dist/types/react/src/index.d.ts +78 -0
- package/package.json +37 -4
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# 0.2.0
|
|
2
|
+
|
|
3
|
+
Cookie consent adapters and success-only action tracking with consent/identity guards. Search filtering and business conversion helpers. React adds an optional Cookie banner, automatic visit/checkout identifiers and backward-compatible explicit keys. Installation generator is a separate maintainer package. Published as public npm packages; production deployment and collection configuration remain separate.
|
|
4
|
+
|
|
5
|
+
# 0.1.0
|
|
6
|
+
|
|
7
|
+
Initial installable SDK: shared event types, consent lifecycle without reload, removable observers, capture-time identity, bounded retry queue, acknowledgment-based delivery, SSR-safe entry and legacy Pixel compatibility. Requires matching API session-statistic deduplication fix for accurate retries.
|
package/README.md
CHANGED
|
@@ -1,3 +1,72 @@
|
|
|
1
|
-
#
|
|
1
|
+
# SenderMaster React 0.2.0
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
React 18 / Next.js 14 are verified. Browser core and types are included; install only this package.
|
|
4
|
+
|
|
5
|
+
```sh
|
|
6
|
+
npm install @sendermaster/react@0.2.0
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## Existing Cookie banner
|
|
10
|
+
|
|
11
|
+
```tsx
|
|
12
|
+
'use client';
|
|
13
|
+
import type { ReactNode } from 'react';
|
|
14
|
+
import { createCookieConsentAdapter, SenderMasterProvider } from '@sendermaster/react';
|
|
15
|
+
const consent = createCookieConsentAdapter({ cookieName: 'analytics_consent', changeEvent: 'my-store:consent-change' });
|
|
16
|
+
export default function Tracking({ children }: { children: ReactNode }) {
|
|
17
|
+
return <SenderMasterProvider enabled={process.env.NEXT_PUBLIC_SENDERMASTER_ENABLED === 'true'}
|
|
18
|
+
siteKey={process.env.NEXT_PUBLIC_SENDERMASTER_SITE_KEY || ''} consentAdapter={consent}>
|
|
19
|
+
{children}
|
|
20
|
+
</SenderMasterProvider>;
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Save the Cookie choice as `granted` or `denied`, then dispatch the configured change event.
|
|
25
|
+
Alternatively call `consent.setConsent(value)`. The connector also checks on focus/visibility changes;
|
|
26
|
+
banners that write a Cookie must signal changes immediately. Custom adapters can supply
|
|
27
|
+
`getSnapshot()` and `subscribe(listener)`. The controlled `analyticsConsent` prop overrides adapters.
|
|
28
|
+
Unknown/denied means no behavior collection. Withdrawal is applied synchronously, and regrant needs no reload.
|
|
29
|
+
|
|
30
|
+
## No existing banner
|
|
31
|
+
|
|
32
|
+
```tsx
|
|
33
|
+
<SenderMasterProvider siteKey={publicSiteKey} enabled={enabled}>
|
|
34
|
+
{children}
|
|
35
|
+
<SenderMasterConsentBanner privacyPolicyUrl="/privacy" />
|
|
36
|
+
</SenderMasterProvider>
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Banner is opt-in. It remembers the analytics choice in a site-specific Cookie and includes Accept,
|
|
40
|
+
Reject and a settings entry. Customize `labels`, `className` and `style`. Marketing defaults to false.
|
|
41
|
+
When using controlled consent or a read-only adapter, the SDK banner is not rendered.
|
|
42
|
+
|
|
43
|
+
## Real business data
|
|
44
|
+
|
|
45
|
+
```tsx
|
|
46
|
+
useProductView(product ? { productId: String(product.id) } : null);
|
|
47
|
+
// For a quick view: useProductView(properties, { active: isOpen }).
|
|
48
|
+
useBeginCheckout(validCheckout ? { items, amount, currency } : null);
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Default visits follow SDK SPA page IDs. The default checkout attempt belongs to a component/page visit.
|
|
52
|
+
Rerenders and price changes do not repeat an event. `viewKey`, `checkoutKey` and `checkoutId` remain
|
|
53
|
+
available for custom flows. Use `active:false` for a closed view. Pass null while business data is unavailable;
|
|
54
|
+
the SDK does not infer whether a merchant's checkout is valid or a payment succeeded.
|
|
55
|
+
|
|
56
|
+
```js
|
|
57
|
+
import { senderMaster } from '@sendermaster/react/browser';
|
|
58
|
+
const events = [{ name: 'add_to_cart', properties: { productId: String(product.id), quantity: 1 } }];
|
|
59
|
+
const response = await senderMaster.trackAfterSuccess(() => addCart(product.id), () => events);
|
|
60
|
+
senderMaster.trackSearch(query, { custom: { region: 'us' } });
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
`trackAfterSuccess` preserves success results and rejection errors. It reports only with consent before
|
|
64
|
+
and after the operation, and skips operations spanning withdrawal/regrant or client replacement.
|
|
65
|
+
The action must reject on a business failure; SDK cannot interpret your API's response format.
|
|
66
|
+
Search helpers trim input and omit empty, long, email-like and phone-like searches by default;
|
|
67
|
+
`filterPersonalData:false` explicitly disables the personal-data heuristic. This is not a guarantee
|
|
68
|
+
that all sensitive terms will be detected. `toId` and `toAmount` assist field conversion.
|
|
69
|
+
|
|
70
|
+
All entry points are safe to import during SSR. Do not mount conflicting Provider configurations in
|
|
71
|
+
one document. Strict Mode reuses the client; final unmount destroys it. Use only a public Site Key.
|
|
72
|
+
No test tools, installation generator or Cookie UI is mounted automatically.
|
package/dist/browser.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";var ne=Object.defineProperty;var De=Object.getOwnPropertyDescriptor;var Le=Object.getOwnPropertyNames;var je=Object.prototype.hasOwnProperty;var Ke=(n,o)=>{for(var s in o)ne(n,s,{get:o[s],enumerable:!0})},Ue=(n,o,s,r)=>{if(o&&typeof o=="object"||typeof o=="function")for(let i of Le(o))!je.call(n,i)&&i!==s&&ne(n,i,{get:()=>o[i],enumerable:!(r=De(o,i))||r.enumerable});return n};var He=n=>Ue(ne({},"__esModule",{value:!0}),n);var st={};Ke(st,{createCookieConsentAdapter:()=>_e,installLegacyPixel:()=>tt,senderMaster:()=>C,toAmount:()=>rt,toId:()=>nt});module.exports=He(st);var We={product_view:[{name:"catalogProductId",type:"string",required:!1,constraint:"1\u2013100; current-site catalog ID"},{name:"catalogVariantId",type:"string",required:!1,constraint:"1\u2013100; requires catalogProductId"},{name:"productId",type:"string",required:!1,constraint:"1\u2013256; required unless catalogProductId is provided"},{name:"variantId",type:"string",required:!1,constraint:"1\u2013256"},{name:"amount",type:"number",required:!1,constraint:"\u2265 0; requires currency"},{name:"currency",type:"string",required:!1,constraint:"3 uppercase letters; requires amount"},{name:"custom",type:"object",required:!1,constraint:"\u2264 50 fields / 3 levels / 16 KB"}],add_to_cart:[{name:"catalogProductId",type:"string",required:!1,constraint:"1\u2013100; current-site catalog ID"},{name:"catalogVariantId",type:"string",required:!1,constraint:"1\u2013100; requires catalogProductId"},{name:"productId",type:"string",required:!1,constraint:"1\u2013256; required unless catalogProductId is provided"},{name:"quantity",type:"integer",required:!0,constraint:"\u2265 1"},{name:"variantId",type:"string",required:!1,constraint:"1\u2013256"},{name:"amount",type:"number",required:!1,constraint:"\u2265 0; requires currency"},{name:"currency",type:"string",required:!1,constraint:"3 uppercase letters; requires amount"},{name:"custom",type:"object",required:!1,constraint:"\u2264 50 fields / 3 levels / 16 KB"}],begin_checkout:[{name:"checkoutId",type:"string",required:!0,constraint:"1\u2013256"},{name:"items",type:"array",required:!0,constraint:"1\u2013100 items"},{name:"amount",type:"number",required:!0,constraint:"\u2265 0"},{name:"currency",type:"string",required:!0,constraint:"3 uppercase letters"},{name:"custom",type:"object",required:!1,constraint:"\u2264 50 fields / 3 levels / 16 KB"}],search:[{name:"query",type:"string",required:!0,constraint:"1\u2013500"},{name:"resultsCount",type:"integer",required:!1,constraint:"\u2265 0"},{name:"custom",type:"object",required:!1,constraint:"\u2264 50 fields / 3 levels / 16 KB"}],wishlist_added:[{name:"catalogProductId",type:"string",required:!1,constraint:"1\u2013100; current-site catalog ID"},{name:"catalogVariantId",type:"string",required:!1,constraint:"1\u2013100; requires catalogProductId"},{name:"productId",type:"string",required:!1,constraint:"1\u2013256; required unless catalogProductId is provided"},{name:"listName",type:"string",required:!1,constraint:"1\u2013256"},{name:"custom",type:"object",required:!1,constraint:"\u2264 50 fields / 3 levels / 16 KB"}]},Je=[{name:"catalogProductId",type:"string",required:!1,constraint:"1\u2013100; current-site catalog ID"},{name:"catalogVariantId",type:"string",required:!1,constraint:"1\u2013100; requires catalogProductId"},{name:"productId",type:"string",required:!1,constraint:"1\u2013256; required unless catalogProductId is provided"},{name:"quantity",type:"integer",required:!0,constraint:"\u2265 1"},{name:"variantId",type:"string",required:!1,constraint:"1\u2013256"},{name:"amount",type:"number",required:!1,constraint:"\u2265 0"}],q=256,Fe=500,Ie=100,be=50,ve=3,Se=16*1024,ze=/(password|passcode|secret|token|api.?key|card.?number|cvv|cvc|security.?code|ssn|passport)/i,Be=Object.fromEntries(Object.entries(We).map(([n,o])=>[n,o.map(s=>s.name)]));function Qe(n,o){let s=[];if(!U(o))return[{path:"properties",message:"must be an object"}];let r=o;for(let i of Object.keys(r))Be[n].includes(i)||s.push({path:`properties.${i}`,message:"is not a supported standard field; place extension data under custom"});return n==="wishlist_added"?(b(r,"productId",s,!r.catalogProductId,q),b(r,"listName",s,!1,q)):n==="product_view"||n==="add_to_cart"?(b(r,"productId",s,!r.catalogProductId,q),b(r,"variantId",s,!1,q),oe(r,"amount",s,!1,!1),we(r,s,!1),r.amount===void 0!=(r.currency===void 0)&&s.push({path:"properties.amount",message:"amount and currency must be provided together"}),n==="add_to_cart"&&ae(r,"quantity",s,!0,1)):n==="begin_checkout"?(b(r,"checkoutId",s,!0,q),oe(r,"amount",s,!0,!1),we(r,s,!0),!Array.isArray(r.items)||r.items.length<1||r.items.length>Ie?s.push({path:"properties.items",message:`must contain 1-${Ie} items`}):r.items.forEach((i,c)=>Xe(i,c,s))):(b(r,"query",s,!0,Fe),ae(r,"resultsCount",s,!1,0)),["product_view","add_to_cart","wishlist_added"].includes(n)&&(b(r,"catalogProductId",s,!1,100),b(r,"catalogVariantId",s,!1,100),r.catalogVariantId&&!r.catalogProductId&&s.push({path:"properties.catalogVariantId",message:"requires catalogProductId"})),r.custom!==void 0&&Ye(r.custom,s),s}function Ee(n,o){let s=Qe(n,o);if(s.length)throw new re(n,s);let r=o,i={};for(let c of["variantId","quantity","checkoutId","items","query","resultsCount","listName","custom"])r[c]!==void 0&&(i[c]=r[c]);return{...typeof r.productId=="string"?{productId:r.productId}:{},...typeof r.catalogProductId=="string"?{catalogProductId:r.catalogProductId}:{},...typeof r.catalogVariantId=="string"?{catalogVariantId:r.catalogVariantId}:{},...typeof r.amount=="number"?{amount:r.amount}:{},...typeof r.currency=="string"?{currency:r.currency}:{},properties:i}}var re=class extends Error{constructor(s,r){super(`Invalid ${s} event: ${r.map(i=>`${i.path} ${i.message}`).join("; ")}`);this.eventName=s;this.issues=r;this.name="StandardEventValidationError"}eventName;issues};function Xe(n,o,s){let r=`properties.items[${o}]`;if(!U(n)){s.push({path:r,message:"must be an object"});return}let i=n,c=Je.map(d=>d.name);for(let d of Object.keys(i))c.includes(d)||s.push({path:`${r}.${d}`,message:"is not supported"});b(i,"productId",s,!i.catalogProductId,q,r),b(i,"catalogProductId",s,!1,100,r),b(i,"catalogVariantId",s,!1,100,r),i.catalogVariantId&&!i.catalogProductId&&s.push({path:`${r}.catalogVariantId`,message:"requires catalogProductId"}),b(i,"variantId",s,!1,q,r),ae(i,"quantity",s,!0,1,r),oe(i,"amount",s,!1,!1,r)}function Ye(n,o){if(!U(n)){o.push({path:"properties.custom",message:"must be an object"});return}let s=n;Object.keys(s).length>be&&o.push({path:"properties.custom",message:`must contain at most ${be} top-level fields`}),se(s,"properties.custom",1,o,new WeakSet);try{new TextEncoder().encode(JSON.stringify(s)).length>Se&&o.push({path:"properties.custom",message:`must be at most ${Se} bytes`})}catch{o.push({path:"properties.custom",message:"must be valid JSON data"})}}function se(n,o,s,r,i){if(s>ve){r.push({path:o,message:`must not exceed ${ve} levels`});return}if(!(n===null||typeof n=="string"||typeof n=="boolean"||typeof n=="number"&&Number.isFinite(n))){if(typeof n=="object"&&n){if(i.has(n)){r.push({path:o,message:"must not contain circular references"});return}i.add(n)}if(Array.isArray(n)){n.forEach((c,d)=>se(c,`${o}[${d}]`,s+1,r,i));return}if(U(n)){Object.entries(n).forEach(([c,d])=>{(c.startsWith("_")||c.toLowerCase().startsWith("sm_"))&&r.push({path:`${o}.${c}`,message:"uses a reserved prefix"}),ze.test(c)&&r.push({path:`${o}.${c}`,message:"must not contain secrets or sensitive payment/identity data"}),se(d,`${o}.${c}`,s+1,r,i)});return}r.push({path:o,message:"must contain JSON-compatible values only"})}}function U(n){if(!n||typeof n!="object"||Array.isArray(n))return!1;let o=Object.getPrototypeOf(n);return o===Object.prototype||o===null}function b(n,o,s,r,i,c="properties"){let d=n[o];if(d===void 0){r&&s.push({path:`${c}.${o}`,message:"is required"});return}(typeof d!="string"||d.length<1||d.length>i)&&s.push({path:`${c}.${o}`,message:`must be a string with 1-${i} characters`})}function oe(n,o,s,r,i,c="properties"){let d=n[o];if(d===void 0){r&&s.push({path:`${c}.${o}`,message:"is required"});return}(typeof d!="number"||!Number.isFinite(d)||(i?d<=0:d<0))&&s.push({path:`${c}.${o}`,message:i?"must be a positive finite number":"must be a non-negative finite number"})}function ae(n,o,s,r,i,c="properties"){let d=n[o];if(d===void 0){r&&s.push({path:`${c}.${o}`,message:"is required"});return}(typeof d!="number"||!Number.isInteger(d)||d<i)&&s.push({path:`${c}.${o}`,message:`must be an integer greater than or equal to ${i}`})}function we(n,o,s){let r=n.currency;if(r===void 0){s&&o.push({path:"properties.currency",message:"is required"});return}(typeof r!="string"||!/^[A-Z]{3}$/.test(r))&&o.push({path:"properties.currency",message:"must be a 3-letter uppercase currency code"})}var Ae=1800*1e3,Ge=1440*60*1e3,Ze=/\.(?:pdf|csv|docx?|xlsx?|pptx?|zip|rar|7z)(?:$|[?#])/i,H=Object.freeze({state:"disabled",consent:"unknown",queueLength:0,pageViewId:null});function Te(n,o=!1){let s=o?"robot_store":`sendermaster:${n.siteKey}`,r={anonymous:`${s}_anonymous_id`,session:`${s}_session`,consent:`${s}_consent`,queue:`${s}_event_queue`},i=new Map;function c(e){try{let t=localStorage.getItem(e);return t!==null&&i.set(e,t),t??i.get(e)??null}catch{return i.get(e)??null}}function d(e,t){i.set(e,t);try{localStorage.setItem(e,t)}catch{}}function T(e){i.delete(e);try{localStorage.removeItem(e)}catch{}}function $(e){try{return JSON.parse(c(e)??"null")}catch{return null}}let R=new Set,_={analytics:"unknown"},k={...H,state:n.enabled===!1||!n.siteKey?"disabled":"waiting_consent"},p=!1,S=0,O,D=!1,L,M=0,P=0,l,W=!1,J=location.href,F=new WeakSet,x=new WeakMap,f=[],z=[];function E(e={}){let t={...k,consent:_.analytics,queueLength:f.length,pageViewId:l?.id??null,...e};if(JSON.stringify(t)!==JSON.stringify(k)){k=Object.freeze(t);for(let a of R)try{a()}catch{}}}function w(e,t,a,u){let g=S,I=A=>{if(p&&S===g)try{a(A)}catch{}};e.addEventListener(t,I,u),z.push(()=>e.removeEventListener(t,I,u))}function ie(){return(n.apiHost??"https://api.sendermaster.com").replace(/\/$/,"")}function B(){let e=c(r.anonymous);return e||(e=crypto.randomUUID(),d(r.anonymous,e)),e}function Q(){let e=$(r.session);return e&&typeof e.id=="string"&&typeof e.lastActivityAt=="number"?e:void 0}function X(){let e=Date.now(),t=Q();if(!t||e-t.lastActivityAt>=Ae){let a={id:crypto.randomUUID(),lastActivityAt:e};return d(r.session,JSON.stringify(a)),a.id}return t.lastActivityAt=e,d(r.session,JSON.stringify(t)),t.id}function Y(){let e=Date.now();f=f.filter(t=>t.siteKey===n.siteKey&&e-Date.parse(t.event.occurredAt)<Ge&&Date.parse(t.event.occurredAt)<=e+6e4).slice(-100)}function j(){Y(),d(r.queue,JSON.stringify(f)),E()}function qe(){let e=$(r.queue);Array.isArray(e)&&(f=e.flatMap(t=>{if(t?.event?.eventId&&typeof t.anonymousId=="string"&&typeof t.sessionId=="string")return[t];let a=c(r.anonymous),u=Q();return o&&t?.eventId&&a&&u?[{siteKey:n.siteKey,anonymousId:a,sessionId:u.id,event:t}]:[]}),Y())}function ce(e){let t=new URL(e);return["email","token","password","access_token"].forEach(a=>t.searchParams.delete(a)),t.toString()}function de(e){try{return new URL(e).origin}catch{return}}function Ce(){return{title:document.title.slice(0,512),language:navigator.language,screen:{width:screen.width,height:screen.height},utm:Object.fromEntries(["utm_source","utm_medium","utm_campaign"].flatMap(e=>{let t=new URL(location.href).searchParams.get(e);return t?[[e,t]]:[]}))}}function Me(e=location.pathname){return n.pageRules?.find(t=>e.startsWith(t.pathPrefix))?.pageType}function ue(){let e=document.documentElement.scrollHeight-innerHeight;return e>0?Math.min(100,Math.max(0,Math.round(scrollY/e*100))):0}function y(e,t={},a={}){if(!p)return;let{productId:u,catalogProductId:g,catalogVariantId:I,amount:A,currency:m,pageType:N,...V}=t,h={eventId:crypto.randomUUID(),name:e,occurredAt:new Date().toISOString(),url:a.url??ce(location.href),path:a.path??location.pathname,...de(document.referrer)?{referrer:de(document.referrer)}:{},...typeof u=="string"?{productId:u}:{},...typeof g=="string"?{catalogProductId:g}:{},...typeof I=="string"?{catalogVariantId:I}:{},...typeof A=="number"?{amount:A}:{},...typeof m=="string"?{currency:m}:{},pageType:a.pageType??(typeof N=="string"?N:l?.pageType),pageViewId:a.pageViewId??l?.id,...a.engagedTimeMsec?{engagedTimeMsec:a.engagedTimeMsec}:{},...Object.keys(V).length?{properties:V}:{},context:Ce()};return f.push({siteKey:n.siteKey,anonymousId:B(),sessionId:X(),event:JSON.parse(JSON.stringify(h))}),j(),f.length>=20&&K(),h.eventId}function Pe(e,t){if(k.state==="disabled")return{queued:!1,reason:"disabled"};if(_.analytics!=="granted")return{queued:!1,reason:"consent_required"};if(!p)return{queued:!1,reason:"unavailable"};try{let a=Ee(e,t),u=y(e,{...a.properties,productId:a.productId,catalogProductId:a.catalogProductId,catalogVariantId:a.catalogVariantId,amount:a.amount,currency:a.currency});return u?{queued:!0,eventId:u}:{queued:!1,reason:"unavailable"}}catch(a){return{queued:!1,reason:"invalid_event",message:a instanceof Error?a.message:"Invalid event"}}}async function K(e=!1){if(!p||D||(Y(),E(),!f.length||!e&&Date.now()<M))return;let t=f[0],a=f.filter(m=>m.siteKey===t.siteKey&&m.anonymousId===t.anonymousId&&m.sessionId===t.sessionId).slice(0,20),u=JSON.stringify({siteKey:t.siteKey,anonymousId:t.anonymousId,sessionId:t.sessionId,events:a.map(m=>m.event)}),g=`${ie()}/v2/collect/events`;if(e)try{if(navigator.sendBeacon?.(g,new Blob([u],{type:"application/json"}))){j();return}}catch{}D=!0;let I=S,A=new AbortController;L=A;try{let m=await fetch(g,{method:"POST",headers:{"content-type":"application/json"},body:u,keepalive:!0,signal:A.signal});if(I!==S||!p)return;if(!m.ok){if(m.status===429||m.status>=500)throw new Error(`Collect HTTP ${m.status}`);let h=new Set(a.map(te=>te.event.eventId));f=f.filter(te=>!h.has(te.event.eventId)),j(),E({state:"error",error:`Collect HTTP ${m.status}: batch discarded`}),M=0,P=0;return}let N=await m.json();if(!Array.isArray(N.results))throw new Error("Collect response missing results");let V=new Set(N.results.filter(h=>h.status==="accepted"||h.status==="duplicate").map(h=>h.eventId));if(!a.every(h=>V.has(h.event.eventId)))throw new Error("Collect response incomplete");if(I!==S||!p)return;f=f.filter(h=>!V.has(h.event.eventId)),P=0,M=0,j(),E({state:"ready",error:void 0,lastDeliveredAt:new Date().toISOString()})}catch(m){if(I!==S||!p)return;P++,M=Date.now()+Math.min(6e4,3e3*2**Math.min(P-1,5)),E({error:m instanceof Error?m.message:"Collect unavailable"})}finally{I===S&&(D=!1,L=void 0)}p&&f.length&&!M&&K()}function le(e,t){let a=JSON.stringify({siteKey:n.siteKey,anonymousId:t,analyticsAllowed:e.analytics==="granted",marketingAllowed:e.marketing??!1,source:e.source??"sdk",policyVersion:e.policyVersion});try{fetch(`${ie()}/v2/collect/consent`,{method:"POST",headers:{"content-type":"application/json"},body:a,keepalive:!0}).then(u=>{if(!u.ok)throw new Error(`Consent HTTP ${u.status}`)}).catch(()=>{})}catch{}}function pe(){l={id:crypto.randomUUID(),url:ce(location.href),path:location.pathname,pageType:Me(),enteredAt:new Date().toISOString(),visibleAt:document.visibilityState==="visible"?Date.now():0,activeMsec:0,reportedMsec:0,maxScrollPercent:ue()},W=!1,y("page_view")}function xe(){!p||!l?.visibleAt||(l.activeMsec+=Date.now()-l.visibleAt,l.visibleAt=0)}function G(e){if(!p||!l)return;xe();let t=l.activeMsec-l.reportedMsec;t<1e3||(l.reportedMsec=l.activeMsec,y("page_engagement",{pageViewId:l.id,maxScrollPercent:l.maxScrollPercent,enteredAt:l.enteredAt,exitReason:e},{pageType:l.pageType,pageViewId:l.id,engagedTimeMsec:t,url:l.url,path:l.path}))}function Ne(){p&&l&&!l.visibleAt&&(l.visibleAt=Date.now())}function me(){!p||location.href===J||(G("navigation"),J=location.href,pe())}function Ve(){let e=S,t=a=>{let u=history[a];history[a]=function(...I){let A=u.apply(this,I);return queueMicrotask(()=>{p&&S===e&&me()}),A};let g=history[a];z.push(()=>{history[a]===g&&(history[a]=u)})};t("pushState"),t("replaceState"),w(window,"popstate",me)}function $e(e){let t=Oe(e),a=Array.from(document.querySelectorAll("video")).indexOf(e);return{videoId:e.dataset.robotVideoId||e.id||t||`video:${location.pathname}:${a}`,videoTitle:e.dataset.robotVideoTitle||e.getAttribute("title")||void 0,productId:e.dataset.robotProductId||void 0,videoSrc:t}}function Z(e,t,a){return{...$e(e),watchedSeconds:Math.round(t.watchedSeconds*10)/10,durationSeconds:Math.round(e.duration*10)/10,...a!==void 0?{progressPercent:a}:{}}}function fe(e,t){let a=Date.now(),u=e.currentTime-t.lastMediaTime,g=(a-t.lastWallTime)/1e3;u>0&&g>0&&u<=Math.max(3,g+1)&&(t.watchedSeconds+=Math.min(u,g+.5)),t.lastMediaTime=e.currentTime,t.lastWallTime=a}function ge(e,t){if(!e.duration)return;let a=Math.min(100,Math.floor(e.currentTime/e.duration*100));for(let u of[25,50,75,100])a>=u&&!t.milestones.has(u)&&(t.milestones.add(u),y("video_progress",Z(e,t,u)))}function Re(){w(window,"scroll",()=>{l&&(l.maxScrollPercent=Math.max(l.maxScrollPercent,ue()),!W&&l.maxScrollPercent>=90&&(W=!0,y("scroll",{percent:90})))},{passive:!0}),w(document,"focusin",e=>{let t=e.target?.closest("form");t&&!F.has(t)&&(F.add(t),y("form_start",{formId:t.id||void 0,formName:t.getAttribute("name")||void 0}))}),w(document,"submit",e=>{let t=e.target;t instanceof HTMLFormElement&&y("form_submitted",{formId:t.id||void 0,formName:t.getAttribute("name")||void 0})}),w(document,"click",e=>{let t=e.target?.closest("a[href]");if(!t)return;let a=t.href,u=t.origin!==location.origin;t.hasAttribute("download")||Ze.test(a)?y("file_download",{fileName:t.pathname.split("/").pop(),linkDomain:t.hostname||void 0}):(u||/^mailto:|^tel:/i.test(t.getAttribute("href")??""))&&y("click",{linkDomain:t.hostname||void 0,linkType:a.startsWith("mailto:")?"email":a.startsWith("tel:")?"phone":"outbound"})}),w(document,"play",e=>{let t=e.target;if(!(t instanceof HTMLVideoElement))return;let a=x.get(t);a||(a={milestones:new Set,watchedSeconds:0,lastMediaTime:t.currentTime,lastWallTime:Date.now(),started:!1},x.set(t,a)),a.started||(a.started=!0,y("video_start",Z(t,a))),a.lastMediaTime=t.currentTime,a.lastWallTime=Date.now()},!0),w(document,"timeupdate",e=>{let t=e.target;if(!(t instanceof HTMLVideoElement))return;let a=x.get(t);a&&(fe(t,a),ge(t,a))},!0),w(document,"ended",e=>{let t=e.target;if(!(t instanceof HTMLVideoElement))return;let a=x.get(t);a&&(fe(t,a),ge(t,a),y("video_complete",Z(t,a,100)))},!0),w(document,"visibilitychange",()=>{document.visibilityState==="hidden"?G("hidden"):Ne()})}function Oe(e){try{return e.currentSrc?new URL(e.currentSrc).origin+new URL(e.currentSrc).pathname:void 0}catch{return}}function ye(){if(!(p||k.state==="disabled"||_.analytics!=="granted"))try{let e=!c(r.anonymous),t=Q();qe(),B(),X(),p=!0,S++,J=location.href,F=new WeakSet,x=new WeakMap,pe(),e&&y("first_visit"),(!t||Date.now()-t.lastActivityAt>=Ae)&&y("session_start"),Re(),Ve(),w(window,"pagehide",()=>{G("pagehide"),K(!0)}),O=window.setInterval(()=>{K()},3e3),E({state:"ready",error:void 0}),window.dispatchEvent(new Event("robot:ready"))}catch(e){ee(!1),E({state:"error",error:e instanceof Error?e.message:"Initialization failed"})}}function ee(e){p=!1,S++,L?.abort(),L=void 0,D=!1,O!==void 0&&window.clearInterval(O),O=void 0;for(let t of z.splice(0).reverse())t();l=void 0,M=0,P=0,e&&(f=[],T(r.queue),T(r.anonymous),T(r.session))}function he(e){if(k.state==="disabled")return;let t=JSON.stringify(_)!==JSON.stringify(e),a=p?c(r.anonymous):null;_={...e},o&&d(r.consent,JSON.stringify({...e,analytics:e.analytics==="granted"})),e.analytics!=="granted"?(ee(e.analytics==="denied"||!!a),E({state:"waiting_consent",error:void 0}),t&&a&&le(e,a)):(ye(),t&&p&&le(e,B()))}return{track:Pe,setConsent:he,start:ye,restoreLegacyConsent:()=>{o&&_.analytics==="unknown"&&$(r.consent)?.analytics===!0&&he({...$(r.consent),analytics:"granted"})},getStatus:()=>k,subscribe:e=>(R.add(e),()=>{R.delete(e)}),getAnonymousId:()=>p?c(r.anonymous):null,getSessionId:()=>p?X():null,destroy:()=>{ee(!1),_={analytics:"unknown"},E({state:"disabled"}),R.clear()}}}function _e({cookieName:n,changeEvent:o="sendermaster:consent-change",grantedValue:s="granted",deniedValue:r="denied",maxAgeDays:i=365}){if(!/^[\w.-]+$/.test(n))throw new Error("Invalid consent cookie name");return{getSnapshot(){if(typeof document>"u")return"unknown";try{let c=document.cookie.split(";").find(T=>T.trim().startsWith(`${n}=`)),d=c?decodeURIComponent(c.trim().slice(n.length+1)):"";return d===s?"granted":d===r?"denied":"unknown"}catch{return"unknown"}},subscribe(c){if(typeof window>"u")return()=>{};let d=()=>c();return window.addEventListener(o,d),window.addEventListener("focus",d),document.addEventListener("visibilitychange",d),()=>{window.removeEventListener(o,d),window.removeEventListener("focus",d),document.removeEventListener("visibilitychange",d)}},setConsent(c){if(typeof document>"u")return;let d=c==="granted"?s:r;document.cookie=`${n}=${c==="unknown"?"":encodeURIComponent(d)}; Path=/; Max-Age=${c==="unknown"?0:Math.max(0,Math.floor(i*86400))}; SameSite=Lax${location.protocol==="https:"?"; Secure":""}`,window.dispatchEvent(new Event(o))}}}var et=Symbol.for("sendermaster.browser.v1");function v(){if(typeof window>"u")return;let n=window;return n[et]||={subscribers:new Set}}function ke(n,o){let s=v();if(!s)return H;let r={...n,siteKey:n.siteKey?.trim()||"",apiHost:(n.apiHost||"https://api.sendermaster.com").replace(/\/$/,""),enabled:n.enabled!==!1},i=JSON.stringify(r);if(s.client&&s.fingerprint===i)return s.client.getStatus();s.client?.destroy(),s.fingerprint=i,s.client=Te(r,o),s.client.subscribe(()=>{for(let c of s.subscribers)try{c()}catch{}});for(let c of s.subscribers)try{c()}catch{}return s.client.getStatus()}var C={init:n=>ke(n,!1),setConsent:n=>v()?.client?.setConsent(n),track(n,o){return v()?.client?.track(n,o)??{queued:!1,reason:"disabled"}},async trackAfterSuccess(n,o){let s=v()?.client,r=s?.getAnonymousId(),i=!!r&&s?.getStatus().consent==="granted",c=await n();if(i&&v()?.client===s&&s?.getAnonymousId()===r&&s.getStatus().consent==="granted")try{let d=o(c);for(let T of Array.isArray(d)?d:[d])C.track(T.name,T.properties)}catch{}return c},trackSearch(n,o={}){let s=n.trim();return!s||s.length>500||o.filterPersonalData!==!1&&/@|(?:\d[\s()+-]*){7,}/.test(s)?{queued:!1,reason:"invalid_event",message:"Search is empty, too long or contains personal data"}:C.track("search",{query:s,...o.custom?{custom:o.custom}:{}})},getStatus:()=>v()?.client?.getStatus()??H,subscribe(n){let o=v();return o?(o.subscribers.add(n),()=>{o.subscribers.delete(n)}):()=>{}},getAnonymousId:()=>v()?.client?.getAnonymousId()??null,getSessionId:()=>v()?.client?.getSessionId()??null,destroy(){let n=v();if(n){n.client?.destroy(),n.client=void 0,n.fingerprint=void 0;for(let o of n.subscribers)try{o()}catch{}}}};function tt(n){ke(n,!0);let o={start:()=>v()?.client?.start(),track:C.track,setConsent:s=>C.setConsent({...s,analytics:s.analytics?"granted":"denied"}),getAnonymousId:C.getAnonymousId,getSessionId:C.getSessionId};return window.robot=o,v()?.client?.restoreLegacyConsent(),o}function nt(n){if(typeof n!="string"&&typeof n!="number")return;let o=String(n).trim();return o&&o!=="0"&&o.length<=256?o:void 0}function rt(n){if(n==null||n===""||typeof n=="boolean")return;let o=Number(n);return Number.isFinite(o)&&o>=0?o:void 0}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './types/react/src/browser';
|
package/dist/browser.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var Re={product_view:[{name:"catalogProductId",type:"string",required:!1,constraint:"1\u2013100; current-site catalog ID"},{name:"catalogVariantId",type:"string",required:!1,constraint:"1\u2013100; requires catalogProductId"},{name:"productId",type:"string",required:!1,constraint:"1\u2013256; required unless catalogProductId is provided"},{name:"variantId",type:"string",required:!1,constraint:"1\u2013256"},{name:"amount",type:"number",required:!1,constraint:"\u2265 0; requires currency"},{name:"currency",type:"string",required:!1,constraint:"3 uppercase letters; requires amount"},{name:"custom",type:"object",required:!1,constraint:"\u2264 50 fields / 3 levels / 16 KB"}],add_to_cart:[{name:"catalogProductId",type:"string",required:!1,constraint:"1\u2013100; current-site catalog ID"},{name:"catalogVariantId",type:"string",required:!1,constraint:"1\u2013100; requires catalogProductId"},{name:"productId",type:"string",required:!1,constraint:"1\u2013256; required unless catalogProductId is provided"},{name:"quantity",type:"integer",required:!0,constraint:"\u2265 1"},{name:"variantId",type:"string",required:!1,constraint:"1\u2013256"},{name:"amount",type:"number",required:!1,constraint:"\u2265 0; requires currency"},{name:"currency",type:"string",required:!1,constraint:"3 uppercase letters; requires amount"},{name:"custom",type:"object",required:!1,constraint:"\u2264 50 fields / 3 levels / 16 KB"}],begin_checkout:[{name:"checkoutId",type:"string",required:!0,constraint:"1\u2013256"},{name:"items",type:"array",required:!0,constraint:"1\u2013100 items"},{name:"amount",type:"number",required:!0,constraint:"\u2265 0"},{name:"currency",type:"string",required:!0,constraint:"3 uppercase letters"},{name:"custom",type:"object",required:!1,constraint:"\u2264 50 fields / 3 levels / 16 KB"}],search:[{name:"query",type:"string",required:!0,constraint:"1\u2013500"},{name:"resultsCount",type:"integer",required:!1,constraint:"\u2265 0"},{name:"custom",type:"object",required:!1,constraint:"\u2264 50 fields / 3 levels / 16 KB"}],wishlist_added:[{name:"catalogProductId",type:"string",required:!1,constraint:"1\u2013100; current-site catalog ID"},{name:"catalogVariantId",type:"string",required:!1,constraint:"1\u2013100; requires catalogProductId"},{name:"productId",type:"string",required:!1,constraint:"1\u2013256; required unless catalogProductId is provided"},{name:"listName",type:"string",required:!1,constraint:"1\u2013256"},{name:"custom",type:"object",required:!1,constraint:"\u2264 50 fields / 3 levels / 16 KB"}]},Oe=[{name:"catalogProductId",type:"string",required:!1,constraint:"1\u2013100; current-site catalog ID"},{name:"catalogVariantId",type:"string",required:!1,constraint:"1\u2013100; requires catalogProductId"},{name:"productId",type:"string",required:!1,constraint:"1\u2013256; required unless catalogProductId is provided"},{name:"quantity",type:"integer",required:!0,constraint:"\u2265 1"},{name:"variantId",type:"string",required:!1,constraint:"1\u2013256"},{name:"amount",type:"number",required:!1,constraint:"\u2265 0"}],q=256,De=500,he=100,Ie=50,be=3,ve=16*1024,Le=/(password|passcode|secret|token|api.?key|card.?number|cvv|cvc|security.?code|ssn|passport)/i,je=Object.fromEntries(Object.entries(Re).map(([n,o])=>[n,o.map(s=>s.name)]));function Ke(n,o){let s=[];if(!U(o))return[{path:"properties",message:"must be an object"}];let r=o;for(let i of Object.keys(r))je[n].includes(i)||s.push({path:`properties.${i}`,message:"is not a supported standard field; place extension data under custom"});return n==="wishlist_added"?(b(r,"productId",s,!r.catalogProductId,q),b(r,"listName",s,!1,q)):n==="product_view"||n==="add_to_cart"?(b(r,"productId",s,!r.catalogProductId,q),b(r,"variantId",s,!1,q),se(r,"amount",s,!1,!1),Se(r,s,!1),r.amount===void 0!=(r.currency===void 0)&&s.push({path:"properties.amount",message:"amount and currency must be provided together"}),n==="add_to_cart"&&oe(r,"quantity",s,!0,1)):n==="begin_checkout"?(b(r,"checkoutId",s,!0,q),se(r,"amount",s,!0,!1),Se(r,s,!0),!Array.isArray(r.items)||r.items.length<1||r.items.length>he?s.push({path:"properties.items",message:`must contain 1-${he} items`}):r.items.forEach((i,c)=>Ue(i,c,s))):(b(r,"query",s,!0,De),oe(r,"resultsCount",s,!1,0)),["product_view","add_to_cart","wishlist_added"].includes(n)&&(b(r,"catalogProductId",s,!1,100),b(r,"catalogVariantId",s,!1,100),r.catalogVariantId&&!r.catalogProductId&&s.push({path:"properties.catalogVariantId",message:"requires catalogProductId"})),r.custom!==void 0&&He(r.custom,s),s}function we(n,o){let s=Ke(n,o);if(s.length)throw new ne(n,s);let r=o,i={};for(let c of["variantId","quantity","checkoutId","items","query","resultsCount","listName","custom"])r[c]!==void 0&&(i[c]=r[c]);return{...typeof r.productId=="string"?{productId:r.productId}:{},...typeof r.catalogProductId=="string"?{catalogProductId:r.catalogProductId}:{},...typeof r.catalogVariantId=="string"?{catalogVariantId:r.catalogVariantId}:{},...typeof r.amount=="number"?{amount:r.amount}:{},...typeof r.currency=="string"?{currency:r.currency}:{},properties:i}}var ne=class extends Error{constructor(s,r){super(`Invalid ${s} event: ${r.map(i=>`${i.path} ${i.message}`).join("; ")}`);this.eventName=s;this.issues=r;this.name="StandardEventValidationError"}eventName;issues};function Ue(n,o,s){let r=`properties.items[${o}]`;if(!U(n)){s.push({path:r,message:"must be an object"});return}let i=n,c=Oe.map(d=>d.name);for(let d of Object.keys(i))c.includes(d)||s.push({path:`${r}.${d}`,message:"is not supported"});b(i,"productId",s,!i.catalogProductId,q,r),b(i,"catalogProductId",s,!1,100,r),b(i,"catalogVariantId",s,!1,100,r),i.catalogVariantId&&!i.catalogProductId&&s.push({path:`${r}.catalogVariantId`,message:"requires catalogProductId"}),b(i,"variantId",s,!1,q,r),oe(i,"quantity",s,!0,1,r),se(i,"amount",s,!1,!1,r)}function He(n,o){if(!U(n)){o.push({path:"properties.custom",message:"must be an object"});return}let s=n;Object.keys(s).length>Ie&&o.push({path:"properties.custom",message:`must contain at most ${Ie} top-level fields`}),re(s,"properties.custom",1,o,new WeakSet);try{new TextEncoder().encode(JSON.stringify(s)).length>ve&&o.push({path:"properties.custom",message:`must be at most ${ve} bytes`})}catch{o.push({path:"properties.custom",message:"must be valid JSON data"})}}function re(n,o,s,r,i){if(s>be){r.push({path:o,message:`must not exceed ${be} levels`});return}if(!(n===null||typeof n=="string"||typeof n=="boolean"||typeof n=="number"&&Number.isFinite(n))){if(typeof n=="object"&&n){if(i.has(n)){r.push({path:o,message:"must not contain circular references"});return}i.add(n)}if(Array.isArray(n)){n.forEach((c,d)=>re(c,`${o}[${d}]`,s+1,r,i));return}if(U(n)){Object.entries(n).forEach(([c,d])=>{(c.startsWith("_")||c.toLowerCase().startsWith("sm_"))&&r.push({path:`${o}.${c}`,message:"uses a reserved prefix"}),Le.test(c)&&r.push({path:`${o}.${c}`,message:"must not contain secrets or sensitive payment/identity data"}),re(d,`${o}.${c}`,s+1,r,i)});return}r.push({path:o,message:"must contain JSON-compatible values only"})}}function U(n){if(!n||typeof n!="object"||Array.isArray(n))return!1;let o=Object.getPrototypeOf(n);return o===Object.prototype||o===null}function b(n,o,s,r,i,c="properties"){let d=n[o];if(d===void 0){r&&s.push({path:`${c}.${o}`,message:"is required"});return}(typeof d!="string"||d.length<1||d.length>i)&&s.push({path:`${c}.${o}`,message:`must be a string with 1-${i} characters`})}function se(n,o,s,r,i,c="properties"){let d=n[o];if(d===void 0){r&&s.push({path:`${c}.${o}`,message:"is required"});return}(typeof d!="number"||!Number.isFinite(d)||(i?d<=0:d<0))&&s.push({path:`${c}.${o}`,message:i?"must be a positive finite number":"must be a non-negative finite number"})}function oe(n,o,s,r,i,c="properties"){let d=n[o];if(d===void 0){r&&s.push({path:`${c}.${o}`,message:"is required"});return}(typeof d!="number"||!Number.isInteger(d)||d<i)&&s.push({path:`${c}.${o}`,message:`must be an integer greater than or equal to ${i}`})}function Se(n,o,s){let r=n.currency;if(r===void 0){s&&o.push({path:"properties.currency",message:"is required"});return}(typeof r!="string"||!/^[A-Z]{3}$/.test(r))&&o.push({path:"properties.currency",message:"must be a 3-letter uppercase currency code"})}var Ee=1800*1e3,We=1440*60*1e3,Je=/\.(?:pdf|csv|docx?|xlsx?|pptx?|zip|rar|7z)(?:$|[?#])/i,H=Object.freeze({state:"disabled",consent:"unknown",queueLength:0,pageViewId:null});function Ae(n,o=!1){let s=o?"robot_store":`sendermaster:${n.siteKey}`,r={anonymous:`${s}_anonymous_id`,session:`${s}_session`,consent:`${s}_consent`,queue:`${s}_event_queue`},i=new Map;function c(e){try{let t=localStorage.getItem(e);return t!==null&&i.set(e,t),t??i.get(e)??null}catch{return i.get(e)??null}}function d(e,t){i.set(e,t);try{localStorage.setItem(e,t)}catch{}}function T(e){i.delete(e);try{localStorage.removeItem(e)}catch{}}function $(e){try{return JSON.parse(c(e)??"null")}catch{return null}}let R=new Set,_={analytics:"unknown"},k={...H,state:n.enabled===!1||!n.siteKey?"disabled":"waiting_consent"},p=!1,S=0,O,D=!1,L,C=0,P=0,l,W=!1,J=location.href,F=new WeakSet,x=new WeakMap,f=[],z=[];function E(e={}){let t={...k,consent:_.analytics,queueLength:f.length,pageViewId:l?.id??null,...e};if(JSON.stringify(t)!==JSON.stringify(k)){k=Object.freeze(t);for(let a of R)try{a()}catch{}}}function w(e,t,a,u){let g=S,I=A=>{if(p&&S===g)try{a(A)}catch{}};e.addEventListener(t,I,u),z.push(()=>e.removeEventListener(t,I,u))}function ae(){return(n.apiHost??"https://api.sendermaster.com").replace(/\/$/,"")}function B(){let e=c(r.anonymous);return e||(e=crypto.randomUUID(),d(r.anonymous,e)),e}function Q(){let e=$(r.session);return e&&typeof e.id=="string"&&typeof e.lastActivityAt=="number"?e:void 0}function X(){let e=Date.now(),t=Q();if(!t||e-t.lastActivityAt>=Ee){let a={id:crypto.randomUUID(),lastActivityAt:e};return d(r.session,JSON.stringify(a)),a.id}return t.lastActivityAt=e,d(r.session,JSON.stringify(t)),t.id}function Y(){let e=Date.now();f=f.filter(t=>t.siteKey===n.siteKey&&e-Date.parse(t.event.occurredAt)<We&&Date.parse(t.event.occurredAt)<=e+6e4).slice(-100)}function j(){Y(),d(r.queue,JSON.stringify(f)),E()}function _e(){let e=$(r.queue);Array.isArray(e)&&(f=e.flatMap(t=>{if(t?.event?.eventId&&typeof t.anonymousId=="string"&&typeof t.sessionId=="string")return[t];let a=c(r.anonymous),u=Q();return o&&t?.eventId&&a&&u?[{siteKey:n.siteKey,anonymousId:a,sessionId:u.id,event:t}]:[]}),Y())}function ie(e){let t=new URL(e);return["email","token","password","access_token"].forEach(a=>t.searchParams.delete(a)),t.toString()}function ce(e){try{return new URL(e).origin}catch{return}}function ke(){return{title:document.title.slice(0,512),language:navigator.language,screen:{width:screen.width,height:screen.height},utm:Object.fromEntries(["utm_source","utm_medium","utm_campaign"].flatMap(e=>{let t=new URL(location.href).searchParams.get(e);return t?[[e,t]]:[]}))}}function qe(e=location.pathname){return n.pageRules?.find(t=>e.startsWith(t.pathPrefix))?.pageType}function de(){let e=document.documentElement.scrollHeight-innerHeight;return e>0?Math.min(100,Math.max(0,Math.round(scrollY/e*100))):0}function y(e,t={},a={}){if(!p)return;let{productId:u,catalogProductId:g,catalogVariantId:I,amount:A,currency:m,pageType:N,...V}=t,h={eventId:crypto.randomUUID(),name:e,occurredAt:new Date().toISOString(),url:a.url??ie(location.href),path:a.path??location.pathname,...ce(document.referrer)?{referrer:ce(document.referrer)}:{},...typeof u=="string"?{productId:u}:{},...typeof g=="string"?{catalogProductId:g}:{},...typeof I=="string"?{catalogVariantId:I}:{},...typeof A=="number"?{amount:A}:{},...typeof m=="string"?{currency:m}:{},pageType:a.pageType??(typeof N=="string"?N:l?.pageType),pageViewId:a.pageViewId??l?.id,...a.engagedTimeMsec?{engagedTimeMsec:a.engagedTimeMsec}:{},...Object.keys(V).length?{properties:V}:{},context:ke()};return f.push({siteKey:n.siteKey,anonymousId:B(),sessionId:X(),event:JSON.parse(JSON.stringify(h))}),j(),f.length>=20&&K(),h.eventId}function Ce(e,t){if(k.state==="disabled")return{queued:!1,reason:"disabled"};if(_.analytics!=="granted")return{queued:!1,reason:"consent_required"};if(!p)return{queued:!1,reason:"unavailable"};try{let a=we(e,t),u=y(e,{...a.properties,productId:a.productId,catalogProductId:a.catalogProductId,catalogVariantId:a.catalogVariantId,amount:a.amount,currency:a.currency});return u?{queued:!0,eventId:u}:{queued:!1,reason:"unavailable"}}catch(a){return{queued:!1,reason:"invalid_event",message:a instanceof Error?a.message:"Invalid event"}}}async function K(e=!1){if(!p||D||(Y(),E(),!f.length||!e&&Date.now()<C))return;let t=f[0],a=f.filter(m=>m.siteKey===t.siteKey&&m.anonymousId===t.anonymousId&&m.sessionId===t.sessionId).slice(0,20),u=JSON.stringify({siteKey:t.siteKey,anonymousId:t.anonymousId,sessionId:t.sessionId,events:a.map(m=>m.event)}),g=`${ae()}/v2/collect/events`;if(e)try{if(navigator.sendBeacon?.(g,new Blob([u],{type:"application/json"}))){j();return}}catch{}D=!0;let I=S,A=new AbortController;L=A;try{let m=await fetch(g,{method:"POST",headers:{"content-type":"application/json"},body:u,keepalive:!0,signal:A.signal});if(I!==S||!p)return;if(!m.ok){if(m.status===429||m.status>=500)throw new Error(`Collect HTTP ${m.status}`);let h=new Set(a.map(te=>te.event.eventId));f=f.filter(te=>!h.has(te.event.eventId)),j(),E({state:"error",error:`Collect HTTP ${m.status}: batch discarded`}),C=0,P=0;return}let N=await m.json();if(!Array.isArray(N.results))throw new Error("Collect response missing results");let V=new Set(N.results.filter(h=>h.status==="accepted"||h.status==="duplicate").map(h=>h.eventId));if(!a.every(h=>V.has(h.event.eventId)))throw new Error("Collect response incomplete");if(I!==S||!p)return;f=f.filter(h=>!V.has(h.event.eventId)),P=0,C=0,j(),E({state:"ready",error:void 0,lastDeliveredAt:new Date().toISOString()})}catch(m){if(I!==S||!p)return;P++,C=Date.now()+Math.min(6e4,3e3*2**Math.min(P-1,5)),E({error:m instanceof Error?m.message:"Collect unavailable"})}finally{I===S&&(D=!1,L=void 0)}p&&f.length&&!C&&K()}function ue(e,t){let a=JSON.stringify({siteKey:n.siteKey,anonymousId:t,analyticsAllowed:e.analytics==="granted",marketingAllowed:e.marketing??!1,source:e.source??"sdk",policyVersion:e.policyVersion});try{fetch(`${ae()}/v2/collect/consent`,{method:"POST",headers:{"content-type":"application/json"},body:a,keepalive:!0}).then(u=>{if(!u.ok)throw new Error(`Consent HTTP ${u.status}`)}).catch(()=>{})}catch{}}function le(){l={id:crypto.randomUUID(),url:ie(location.href),path:location.pathname,pageType:qe(),enteredAt:new Date().toISOString(),visibleAt:document.visibilityState==="visible"?Date.now():0,activeMsec:0,reportedMsec:0,maxScrollPercent:de()},W=!1,y("page_view")}function Me(){!p||!l?.visibleAt||(l.activeMsec+=Date.now()-l.visibleAt,l.visibleAt=0)}function G(e){if(!p||!l)return;Me();let t=l.activeMsec-l.reportedMsec;t<1e3||(l.reportedMsec=l.activeMsec,y("page_engagement",{pageViewId:l.id,maxScrollPercent:l.maxScrollPercent,enteredAt:l.enteredAt,exitReason:e},{pageType:l.pageType,pageViewId:l.id,engagedTimeMsec:t,url:l.url,path:l.path}))}function Pe(){p&&l&&!l.visibleAt&&(l.visibleAt=Date.now())}function pe(){!p||location.href===J||(G("navigation"),J=location.href,le())}function xe(){let e=S,t=a=>{let u=history[a];history[a]=function(...I){let A=u.apply(this,I);return queueMicrotask(()=>{p&&S===e&&pe()}),A};let g=history[a];z.push(()=>{history[a]===g&&(history[a]=u)})};t("pushState"),t("replaceState"),w(window,"popstate",pe)}function Ne(e){let t=$e(e),a=Array.from(document.querySelectorAll("video")).indexOf(e);return{videoId:e.dataset.robotVideoId||e.id||t||`video:${location.pathname}:${a}`,videoTitle:e.dataset.robotVideoTitle||e.getAttribute("title")||void 0,productId:e.dataset.robotProductId||void 0,videoSrc:t}}function Z(e,t,a){return{...Ne(e),watchedSeconds:Math.round(t.watchedSeconds*10)/10,durationSeconds:Math.round(e.duration*10)/10,...a!==void 0?{progressPercent:a}:{}}}function me(e,t){let a=Date.now(),u=e.currentTime-t.lastMediaTime,g=(a-t.lastWallTime)/1e3;u>0&&g>0&&u<=Math.max(3,g+1)&&(t.watchedSeconds+=Math.min(u,g+.5)),t.lastMediaTime=e.currentTime,t.lastWallTime=a}function fe(e,t){if(!e.duration)return;let a=Math.min(100,Math.floor(e.currentTime/e.duration*100));for(let u of[25,50,75,100])a>=u&&!t.milestones.has(u)&&(t.milestones.add(u),y("video_progress",Z(e,t,u)))}function Ve(){w(window,"scroll",()=>{l&&(l.maxScrollPercent=Math.max(l.maxScrollPercent,de()),!W&&l.maxScrollPercent>=90&&(W=!0,y("scroll",{percent:90})))},{passive:!0}),w(document,"focusin",e=>{let t=e.target?.closest("form");t&&!F.has(t)&&(F.add(t),y("form_start",{formId:t.id||void 0,formName:t.getAttribute("name")||void 0}))}),w(document,"submit",e=>{let t=e.target;t instanceof HTMLFormElement&&y("form_submitted",{formId:t.id||void 0,formName:t.getAttribute("name")||void 0})}),w(document,"click",e=>{let t=e.target?.closest("a[href]");if(!t)return;let a=t.href,u=t.origin!==location.origin;t.hasAttribute("download")||Je.test(a)?y("file_download",{fileName:t.pathname.split("/").pop(),linkDomain:t.hostname||void 0}):(u||/^mailto:|^tel:/i.test(t.getAttribute("href")??""))&&y("click",{linkDomain:t.hostname||void 0,linkType:a.startsWith("mailto:")?"email":a.startsWith("tel:")?"phone":"outbound"})}),w(document,"play",e=>{let t=e.target;if(!(t instanceof HTMLVideoElement))return;let a=x.get(t);a||(a={milestones:new Set,watchedSeconds:0,lastMediaTime:t.currentTime,lastWallTime:Date.now(),started:!1},x.set(t,a)),a.started||(a.started=!0,y("video_start",Z(t,a))),a.lastMediaTime=t.currentTime,a.lastWallTime=Date.now()},!0),w(document,"timeupdate",e=>{let t=e.target;if(!(t instanceof HTMLVideoElement))return;let a=x.get(t);a&&(me(t,a),fe(t,a))},!0),w(document,"ended",e=>{let t=e.target;if(!(t instanceof HTMLVideoElement))return;let a=x.get(t);a&&(me(t,a),fe(t,a),y("video_complete",Z(t,a,100)))},!0),w(document,"visibilitychange",()=>{document.visibilityState==="hidden"?G("hidden"):Pe()})}function $e(e){try{return e.currentSrc?new URL(e.currentSrc).origin+new URL(e.currentSrc).pathname:void 0}catch{return}}function ge(){if(!(p||k.state==="disabled"||_.analytics!=="granted"))try{let e=!c(r.anonymous),t=Q();_e(),B(),X(),p=!0,S++,J=location.href,F=new WeakSet,x=new WeakMap,le(),e&&y("first_visit"),(!t||Date.now()-t.lastActivityAt>=Ee)&&y("session_start"),Ve(),xe(),w(window,"pagehide",()=>{G("pagehide"),K(!0)}),O=window.setInterval(()=>{K()},3e3),E({state:"ready",error:void 0}),window.dispatchEvent(new Event("robot:ready"))}catch(e){ee(!1),E({state:"error",error:e instanceof Error?e.message:"Initialization failed"})}}function ee(e){p=!1,S++,L?.abort(),L=void 0,D=!1,O!==void 0&&window.clearInterval(O),O=void 0;for(let t of z.splice(0).reverse())t();l=void 0,C=0,P=0,e&&(f=[],T(r.queue),T(r.anonymous),T(r.session))}function ye(e){if(k.state==="disabled")return;let t=JSON.stringify(_)!==JSON.stringify(e),a=p?c(r.anonymous):null;_={...e},o&&d(r.consent,JSON.stringify({...e,analytics:e.analytics==="granted"})),e.analytics!=="granted"?(ee(e.analytics==="denied"||!!a),E({state:"waiting_consent",error:void 0}),t&&a&&ue(e,a)):(ge(),t&&p&&ue(e,B()))}return{track:Ce,setConsent:ye,start:ge,restoreLegacyConsent:()=>{o&&_.analytics==="unknown"&&$(r.consent)?.analytics===!0&&ye({...$(r.consent),analytics:"granted"})},getStatus:()=>k,subscribe:e=>(R.add(e),()=>{R.delete(e)}),getAnonymousId:()=>p?c(r.anonymous):null,getSessionId:()=>p?X():null,destroy:()=>{ee(!1),_={analytics:"unknown"},E({state:"disabled"}),R.clear()}}}function Fe({cookieName:n,changeEvent:o="sendermaster:consent-change",grantedValue:s="granted",deniedValue:r="denied",maxAgeDays:i=365}){if(!/^[\w.-]+$/.test(n))throw new Error("Invalid consent cookie name");return{getSnapshot(){if(typeof document>"u")return"unknown";try{let c=document.cookie.split(";").find(T=>T.trim().startsWith(`${n}=`)),d=c?decodeURIComponent(c.trim().slice(n.length+1)):"";return d===s?"granted":d===r?"denied":"unknown"}catch{return"unknown"}},subscribe(c){if(typeof window>"u")return()=>{};let d=()=>c();return window.addEventListener(o,d),window.addEventListener("focus",d),document.addEventListener("visibilitychange",d),()=>{window.removeEventListener(o,d),window.removeEventListener("focus",d),document.removeEventListener("visibilitychange",d)}},setConsent(c){if(typeof document>"u")return;let d=c==="granted"?s:r;document.cookie=`${n}=${c==="unknown"?"":encodeURIComponent(d)}; Path=/; Max-Age=${c==="unknown"?0:Math.max(0,Math.floor(i*86400))}; SameSite=Lax${location.protocol==="https:"?"; Secure":""}`,window.dispatchEvent(new Event(o))}}}var ze=Symbol.for("sendermaster.browser.v1");function v(){if(typeof window>"u")return;let n=window;return n[ze]||={subscribers:new Set}}function Te(n,o){let s=v();if(!s)return H;let r={...n,siteKey:n.siteKey?.trim()||"",apiHost:(n.apiHost||"https://api.sendermaster.com").replace(/\/$/,""),enabled:n.enabled!==!1},i=JSON.stringify(r);if(s.client&&s.fingerprint===i)return s.client.getStatus();s.client?.destroy(),s.fingerprint=i,s.client=Ae(r,o),s.client.subscribe(()=>{for(let c of s.subscribers)try{c()}catch{}});for(let c of s.subscribers)try{c()}catch{}return s.client.getStatus()}var M={init:n=>Te(n,!1),setConsent:n=>v()?.client?.setConsent(n),track(n,o){return v()?.client?.track(n,o)??{queued:!1,reason:"disabled"}},async trackAfterSuccess(n,o){let s=v()?.client,r=s?.getAnonymousId(),i=!!r&&s?.getStatus().consent==="granted",c=await n();if(i&&v()?.client===s&&s?.getAnonymousId()===r&&s.getStatus().consent==="granted")try{let d=o(c);for(let T of Array.isArray(d)?d:[d])M.track(T.name,T.properties)}catch{}return c},trackSearch(n,o={}){let s=n.trim();return!s||s.length>500||o.filterPersonalData!==!1&&/@|(?:\d[\s()+-]*){7,}/.test(s)?{queued:!1,reason:"invalid_event",message:"Search is empty, too long or contains personal data"}:M.track("search",{query:s,...o.custom?{custom:o.custom}:{}})},getStatus:()=>v()?.client?.getStatus()??H,subscribe(n){let o=v();return o?(o.subscribers.add(n),()=>{o.subscribers.delete(n)}):()=>{}},getAnonymousId:()=>v()?.client?.getAnonymousId()??null,getSessionId:()=>v()?.client?.getSessionId()??null,destroy(){let n=v();if(n){n.client?.destroy(),n.client=void 0,n.fingerprint=void 0;for(let o of n.subscribers)try{o()}catch{}}}};function et(n){Te(n,!0);let o={start:()=>v()?.client?.start(),track:M.track,setConsent:s=>M.setConsent({...s,analytics:s.analytics?"granted":"denied"}),getAnonymousId:M.getAnonymousId,getSessionId:M.getSessionId};return window.robot=o,v()?.client?.restoreLegacyConsent(),o}function tt(n){if(typeof n!="string"&&typeof n!="number")return;let o=String(n).trim();return o&&o!=="0"&&o.length<=256?o:void 0}function nt(n){if(n==null||n===""||typeof n=="boolean")return;let o=Number(n);return Number.isFinite(o)&&o>=0?o:void 0}export{Fe as createCookieConsentAdapter,et as installLegacyPixel,M as senderMaster,nt as toAmount,tt as toId};
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use strict";"use client";var oe=Object.defineProperty;var Je=Object.getOwnPropertyDescriptor;var Be=Object.getOwnPropertyNames;var ze=Object.prototype.hasOwnProperty;var Fe=(e,o)=>{for(var s in o)oe(e,s,{get:o[s],enumerable:!0})},Qe=(e,o,s,r)=>{if(o&&typeof o=="object"||typeof o=="function")for(let i of Be(o))!ze.call(e,i)&&i!==s&&oe(e,i,{get:()=>o[i],enumerable:!(r=Je(o,i))||r.enumerable});return e};var Xe=e=>Qe(oe({},"__esModule",{value:!0}),e);var mt={};Fe(mt,{SenderMasterConsentBanner:()=>gt,SenderMasterProvider:()=>lt,createCookieConsentAdapter:()=>B,installLegacyPixel:()=>ct,senderMaster:()=>I,toAmount:()=>ut,toId:()=>dt,useBeginCheckout:()=>ft,useProductView:()=>pt,useSenderMaster:()=>fe});module.exports=Xe(mt);var f=require("react");var Ye={product_view:[{name:"catalogProductId",type:"string",required:!1,constraint:"1\u2013100; current-site catalog ID"},{name:"catalogVariantId",type:"string",required:!1,constraint:"1\u2013100; requires catalogProductId"},{name:"productId",type:"string",required:!1,constraint:"1\u2013256; required unless catalogProductId is provided"},{name:"variantId",type:"string",required:!1,constraint:"1\u2013256"},{name:"amount",type:"number",required:!1,constraint:"\u2265 0; requires currency"},{name:"currency",type:"string",required:!1,constraint:"3 uppercase letters; requires amount"},{name:"custom",type:"object",required:!1,constraint:"\u2264 50 fields / 3 levels / 16 KB"}],add_to_cart:[{name:"catalogProductId",type:"string",required:!1,constraint:"1\u2013100; current-site catalog ID"},{name:"catalogVariantId",type:"string",required:!1,constraint:"1\u2013100; requires catalogProductId"},{name:"productId",type:"string",required:!1,constraint:"1\u2013256; required unless catalogProductId is provided"},{name:"quantity",type:"integer",required:!0,constraint:"\u2265 1"},{name:"variantId",type:"string",required:!1,constraint:"1\u2013256"},{name:"amount",type:"number",required:!1,constraint:"\u2265 0; requires currency"},{name:"currency",type:"string",required:!1,constraint:"3 uppercase letters; requires amount"},{name:"custom",type:"object",required:!1,constraint:"\u2264 50 fields / 3 levels / 16 KB"}],begin_checkout:[{name:"checkoutId",type:"string",required:!0,constraint:"1\u2013256"},{name:"items",type:"array",required:!0,constraint:"1\u2013100 items"},{name:"amount",type:"number",required:!0,constraint:"\u2265 0"},{name:"currency",type:"string",required:!0,constraint:"3 uppercase letters"},{name:"custom",type:"object",required:!1,constraint:"\u2264 50 fields / 3 levels / 16 KB"}],search:[{name:"query",type:"string",required:!0,constraint:"1\u2013500"},{name:"resultsCount",type:"integer",required:!1,constraint:"\u2265 0"},{name:"custom",type:"object",required:!1,constraint:"\u2264 50 fields / 3 levels / 16 KB"}],wishlist_added:[{name:"catalogProductId",type:"string",required:!1,constraint:"1\u2013100; current-site catalog ID"},{name:"catalogVariantId",type:"string",required:!1,constraint:"1\u2013100; requires catalogProductId"},{name:"productId",type:"string",required:!1,constraint:"1\u2013256; required unless catalogProductId is provided"},{name:"listName",type:"string",required:!1,constraint:"1\u2013256"},{name:"custom",type:"object",required:!1,constraint:"\u2264 50 fields / 3 levels / 16 KB"}]},Ge=[{name:"catalogProductId",type:"string",required:!1,constraint:"1\u2013100; current-site catalog ID"},{name:"catalogVariantId",type:"string",required:!1,constraint:"1\u2013100; requires catalogProductId"},{name:"productId",type:"string",required:!1,constraint:"1\u2013256; required unless catalogProductId is provided"},{name:"quantity",type:"integer",required:!0,constraint:"\u2265 1"},{name:"variantId",type:"string",required:!1,constraint:"1\u2013256"},{name:"amount",type:"number",required:!1,constraint:"\u2265 0"}],V=256,Ze=500,Ce=100,Ae=50,_e=3,Pe=16*1024,et=/(password|passcode|secret|token|api.?key|card.?number|cvv|cvc|security.?code|ssn|passport)/i,tt=Object.fromEntries(Object.entries(Ye).map(([e,o])=>[e,o.map(s=>s.name)]));function nt(e,o){let s=[];if(!J(o))return[{path:"properties",message:"must be an object"}];let r=o;for(let i of Object.keys(r))tt[e].includes(i)||s.push({path:`properties.${i}`,message:"is not a supported standard field; place extension data under custom"});return e==="wishlist_added"?(_(r,"productId",s,!r.catalogProductId,V),_(r,"listName",s,!1,V)):e==="product_view"||e==="add_to_cart"?(_(r,"productId",s,!r.catalogProductId,V),_(r,"variantId",s,!1,V),ce(r,"amount",s,!1,!1),xe(r,s,!1),r.amount===void 0!=(r.currency===void 0)&&s.push({path:"properties.amount",message:"amount and currency must be provided together"}),e==="add_to_cart"&&de(r,"quantity",s,!0,1)):e==="begin_checkout"?(_(r,"checkoutId",s,!0,V),ce(r,"amount",s,!0,!1),xe(r,s,!0),!Array.isArray(r.items)||r.items.length<1||r.items.length>Ce?s.push({path:"properties.items",message:`must contain 1-${Ce} items`}):r.items.forEach((i,c)=>rt(i,c,s))):(_(r,"query",s,!0,Ze),de(r,"resultsCount",s,!1,0)),["product_view","add_to_cart","wishlist_added"].includes(e)&&(_(r,"catalogProductId",s,!1,100),_(r,"catalogVariantId",s,!1,100),r.catalogVariantId&&!r.catalogProductId&&s.push({path:"properties.catalogVariantId",message:"requires catalogProductId"})),r.custom!==void 0&&st(r.custom,s),s}function Te(e,o){let s=nt(e,o);if(s.length)throw new ae(e,s);let r=o,i={};for(let c of["variantId","quantity","checkoutId","items","query","resultsCount","listName","custom"])r[c]!==void 0&&(i[c]=r[c]);return{...typeof r.productId=="string"?{productId:r.productId}:{},...typeof r.catalogProductId=="string"?{catalogProductId:r.catalogProductId}:{},...typeof r.catalogVariantId=="string"?{catalogVariantId:r.catalogVariantId}:{},...typeof r.amount=="number"?{amount:r.amount}:{},...typeof r.currency=="string"?{currency:r.currency}:{},properties:i}}var ae=class extends Error{constructor(s,r){super(`Invalid ${s} event: ${r.map(i=>`${i.path} ${i.message}`).join("; ")}`);this.eventName=s;this.issues=r;this.name="StandardEventValidationError"}eventName;issues};function rt(e,o,s){let r=`properties.items[${o}]`;if(!J(e)){s.push({path:r,message:"must be an object"});return}let i=e,c=Ge.map(d=>d.name);for(let d of Object.keys(i))c.includes(d)||s.push({path:`${r}.${d}`,message:"is not supported"});_(i,"productId",s,!i.catalogProductId,V,r),_(i,"catalogProductId",s,!1,100,r),_(i,"catalogVariantId",s,!1,100,r),i.catalogVariantId&&!i.catalogProductId&&s.push({path:`${r}.catalogVariantId`,message:"requires catalogProductId"}),_(i,"variantId",s,!1,V,r),de(i,"quantity",s,!0,1,r),ce(i,"amount",s,!1,!1,r)}function st(e,o){if(!J(e)){o.push({path:"properties.custom",message:"must be an object"});return}let s=e;Object.keys(s).length>Ae&&o.push({path:"properties.custom",message:`must contain at most ${Ae} top-level fields`}),ie(s,"properties.custom",1,o,new WeakSet);try{new TextEncoder().encode(JSON.stringify(s)).length>Pe&&o.push({path:"properties.custom",message:`must be at most ${Pe} bytes`})}catch{o.push({path:"properties.custom",message:"must be valid JSON data"})}}function ie(e,o,s,r,i){if(s>_e){r.push({path:o,message:`must not exceed ${_e} levels`});return}if(!(e===null||typeof e=="string"||typeof e=="boolean"||typeof e=="number"&&Number.isFinite(e))){if(typeof e=="object"&&e){if(i.has(e)){r.push({path:o,message:"must not contain circular references"});return}i.add(e)}if(Array.isArray(e)){e.forEach((c,d)=>ie(c,`${o}[${d}]`,s+1,r,i));return}if(J(e)){Object.entries(e).forEach(([c,d])=>{(c.startsWith("_")||c.toLowerCase().startsWith("sm_"))&&r.push({path:`${o}.${c}`,message:"uses a reserved prefix"}),et.test(c)&&r.push({path:`${o}.${c}`,message:"must not contain secrets or sensitive payment/identity data"}),ie(d,`${o}.${c}`,s+1,r,i)});return}r.push({path:o,message:"must contain JSON-compatible values only"})}}function J(e){if(!e||typeof e!="object"||Array.isArray(e))return!1;let o=Object.getPrototypeOf(e);return o===Object.prototype||o===null}function _(e,o,s,r,i,c="properties"){let d=e[o];if(d===void 0){r&&s.push({path:`${c}.${o}`,message:"is required"});return}(typeof d!="string"||d.length<1||d.length>i)&&s.push({path:`${c}.${o}`,message:`must be a string with 1-${i} characters`})}function ce(e,o,s,r,i,c="properties"){let d=e[o];if(d===void 0){r&&s.push({path:`${c}.${o}`,message:"is required"});return}(typeof d!="number"||!Number.isFinite(d)||(i?d<=0:d<0))&&s.push({path:`${c}.${o}`,message:i?"must be a positive finite number":"must be a non-negative finite number"})}function de(e,o,s,r,i,c="properties"){let d=e[o];if(d===void 0){r&&s.push({path:`${c}.${o}`,message:"is required"});return}(typeof d!="number"||!Number.isInteger(d)||d<i)&&s.push({path:`${c}.${o}`,message:`must be an integer greater than or equal to ${i}`})}function xe(e,o,s){let r=e.currency;if(r===void 0){s&&o.push({path:"properties.currency",message:"is required"});return}(typeof r!="string"||!/^[A-Z]{3}$/.test(r))&&o.push({path:"properties.currency",message:"must be a 3-letter uppercase currency code"})}var Me=1800*1e3,ot=1440*60*1e3,at=/\.(?:pdf|csv|docx?|xlsx?|pptx?|zip|rar|7z)(?:$|[?#])/i,O=Object.freeze({state:"disabled",consent:"unknown",queueLength:0,pageViewId:null});function qe(e,o=!1){let s=o?"robot_store":`sendermaster:${e.siteKey}`,r={anonymous:`${s}_anonymous_id`,session:`${s}_session`,consent:`${s}_consent`,queue:`${s}_event_queue`},i=new Map;function c(t){try{let n=localStorage.getItem(t);return n!==null&&i.set(t,n),n??i.get(t)??null}catch{return i.get(t)??null}}function d(t,n){i.set(t,n);try{localStorage.setItem(t,n)}catch{}}function g(t){i.delete(t);try{localStorage.removeItem(t)}catch{}}function w(t){try{return JSON.parse(c(t)??"null")}catch{return null}}let v=new Set,m={analytics:"unknown"},E={...O,state:e.enabled===!1||!e.siteKey?"disabled":"waiting_consent"},p=!1,h=0,N,$=!1,U,R=0,D=0,l,z=!1,F=location.href,Q=new WeakSet,L=new WeakMap,b=[],X=[];function M(t={}){let n={...E,consent:m.analytics,queueLength:b.length,pageViewId:l?.id??null,...t};if(JSON.stringify(n)!==JSON.stringify(E)){E=Object.freeze(n);for(let a of v)try{a()}catch{}}}function T(t,n,a,u){let S=h,A=q=>{if(p&&h===S)try{a(q)}catch{}};t.addEventListener(n,A,u),X.push(()=>t.removeEventListener(n,A,u))}function ge(){return(e.apiHost??"https://api.sendermaster.com").replace(/\/$/,"")}function Y(){let t=c(r.anonymous);return t||(t=crypto.randomUUID(),d(r.anonymous,t)),t}function G(){let t=w(r.session);return t&&typeof t.id=="string"&&typeof t.lastActivityAt=="number"?t:void 0}function Z(){let t=Date.now(),n=G();if(!n||t-n.lastActivityAt>=Me){let a={id:crypto.randomUUID(),lastActivityAt:t};return d(r.session,JSON.stringify(a)),a.id}return n.lastActivityAt=t,d(r.session,JSON.stringify(n)),n.id}function ee(){let t=Date.now();b=b.filter(n=>n.siteKey===e.siteKey&&t-Date.parse(n.event.occurredAt)<ot&&Date.parse(n.event.occurredAt)<=t+6e4).slice(-100)}function H(){ee(),d(r.queue,JSON.stringify(b)),M()}function $e(){let t=w(r.queue);Array.isArray(t)&&(b=t.flatMap(n=>{if(n?.event?.eventId&&typeof n.anonymousId=="string"&&typeof n.sessionId=="string")return[n];let a=c(r.anonymous),u=G();return o&&n?.eventId&&a&&u?[{siteKey:e.siteKey,anonymousId:a,sessionId:u.id,event:n}]:[]}),ee())}function me(t){let n=new URL(t);return["email","token","password","access_token"].forEach(a=>n.searchParams.delete(a)),n.toString()}function ye(t){try{return new URL(t).origin}catch{return}}function Re(){return{title:document.title.slice(0,512),language:navigator.language,screen:{width:screen.width,height:screen.height},utm:Object.fromEntries(["utm_source","utm_medium","utm_campaign"].flatMap(t=>{let n=new URL(location.href).searchParams.get(t);return n?[[t,n]]:[]}))}}function Oe(t=location.pathname){return e.pageRules?.find(n=>t.startsWith(n.pathPrefix))?.pageType}function he(){let t=document.documentElement.scrollHeight-innerHeight;return t>0?Math.min(100,Math.max(0,Math.round(scrollY/t*100))):0}function k(t,n={},a={}){if(!p)return;let{productId:u,catalogProductId:S,catalogVariantId:A,amount:q,currency:y,pageType:j,...K}=n,C={eventId:crypto.randomUUID(),name:t,occurredAt:new Date().toISOString(),url:a.url??me(location.href),path:a.path??location.pathname,...ye(document.referrer)?{referrer:ye(document.referrer)}:{},...typeof u=="string"?{productId:u}:{},...typeof S=="string"?{catalogProductId:S}:{},...typeof A=="string"?{catalogVariantId:A}:{},...typeof q=="number"?{amount:q}:{},...typeof y=="string"?{currency:y}:{},pageType:a.pageType??(typeof j=="string"?j:l?.pageType),pageViewId:a.pageViewId??l?.id,...a.engagedTimeMsec?{engagedTimeMsec:a.engagedTimeMsec}:{},...Object.keys(K).length?{properties:K}:{},context:Re()};return b.push({siteKey:e.siteKey,anonymousId:Y(),sessionId:Z(),event:JSON.parse(JSON.stringify(C))}),H(),b.length>=20&&W(),C.eventId}function De(t,n){if(E.state==="disabled")return{queued:!1,reason:"disabled"};if(m.analytics!=="granted")return{queued:!1,reason:"consent_required"};if(!p)return{queued:!1,reason:"unavailable"};try{let a=Te(t,n),u=k(t,{...a.properties,productId:a.productId,catalogProductId:a.catalogProductId,catalogVariantId:a.catalogVariantId,amount:a.amount,currency:a.currency});return u?{queued:!0,eventId:u}:{queued:!1,reason:"unavailable"}}catch(a){return{queued:!1,reason:"invalid_event",message:a instanceof Error?a.message:"Invalid event"}}}async function W(t=!1){if(!p||$||(ee(),M(),!b.length||!t&&Date.now()<R))return;let n=b[0],a=b.filter(y=>y.siteKey===n.siteKey&&y.anonymousId===n.anonymousId&&y.sessionId===n.sessionId).slice(0,20),u=JSON.stringify({siteKey:n.siteKey,anonymousId:n.anonymousId,sessionId:n.sessionId,events:a.map(y=>y.event)}),S=`${ge()}/v2/collect/events`;if(t)try{if(navigator.sendBeacon?.(S,new Blob([u],{type:"application/json"}))){H();return}}catch{}$=!0;let A=h,q=new AbortController;U=q;try{let y=await fetch(S,{method:"POST",headers:{"content-type":"application/json"},body:u,keepalive:!0,signal:q.signal});if(A!==h||!p)return;if(!y.ok){if(y.status===429||y.status>=500)throw new Error(`Collect HTTP ${y.status}`);let C=new Set(a.map(se=>se.event.eventId));b=b.filter(se=>!C.has(se.event.eventId)),H(),M({state:"error",error:`Collect HTTP ${y.status}: batch discarded`}),R=0,D=0;return}let j=await y.json();if(!Array.isArray(j.results))throw new Error("Collect response missing results");let K=new Set(j.results.filter(C=>C.status==="accepted"||C.status==="duplicate").map(C=>C.eventId));if(!a.every(C=>K.has(C.event.eventId)))throw new Error("Collect response incomplete");if(A!==h||!p)return;b=b.filter(C=>!K.has(C.event.eventId)),D=0,R=0,H(),M({state:"ready",error:void 0,lastDeliveredAt:new Date().toISOString()})}catch(y){if(A!==h||!p)return;D++,R=Date.now()+Math.min(6e4,3e3*2**Math.min(D-1,5)),M({error:y instanceof Error?y.message:"Collect unavailable"})}finally{A===h&&($=!1,U=void 0)}p&&b.length&&!R&&W()}function be(t,n){let a=JSON.stringify({siteKey:e.siteKey,anonymousId:n,analyticsAllowed:t.analytics==="granted",marketingAllowed:t.marketing??!1,source:t.source??"sdk",policyVersion:t.policyVersion});try{fetch(`${ge()}/v2/collect/consent`,{method:"POST",headers:{"content-type":"application/json"},body:a,keepalive:!0}).then(u=>{if(!u.ok)throw new Error(`Consent HTTP ${u.status}`)}).catch(()=>{})}catch{}}function Ie(){l={id:crypto.randomUUID(),url:me(location.href),path:location.pathname,pageType:Oe(),enteredAt:new Date().toISOString(),visibleAt:document.visibilityState==="visible"?Date.now():0,activeMsec:0,reportedMsec:0,maxScrollPercent:he()},z=!1,k("page_view")}function Le(){!p||!l?.visibleAt||(l.activeMsec+=Date.now()-l.visibleAt,l.visibleAt=0)}function te(t){if(!p||!l)return;Le();let n=l.activeMsec-l.reportedMsec;n<1e3||(l.reportedMsec=l.activeMsec,k("page_engagement",{pageViewId:l.id,maxScrollPercent:l.maxScrollPercent,enteredAt:l.enteredAt,exitReason:t},{pageType:l.pageType,pageViewId:l.id,engagedTimeMsec:n,url:l.url,path:l.path}))}function je(){p&&l&&!l.visibleAt&&(l.visibleAt=Date.now())}function ve(){!p||location.href===F||(te("navigation"),F=location.href,Ie())}function Ke(){let t=h,n=a=>{let u=history[a];history[a]=function(...A){let q=u.apply(this,A);return queueMicrotask(()=>{p&&h===t&&ve()}),q};let S=history[a];X.push(()=>{history[a]===S&&(history[a]=u)})};n("pushState"),n("replaceState"),T(window,"popstate",ve)}function Ue(t){let n=We(t),a=Array.from(document.querySelectorAll("video")).indexOf(t);return{videoId:t.dataset.robotVideoId||t.id||n||`video:${location.pathname}:${a}`,videoTitle:t.dataset.robotVideoTitle||t.getAttribute("title")||void 0,productId:t.dataset.robotProductId||void 0,videoSrc:n}}function ne(t,n,a){return{...Ue(t),watchedSeconds:Math.round(n.watchedSeconds*10)/10,durationSeconds:Math.round(t.duration*10)/10,...a!==void 0?{progressPercent:a}:{}}}function Se(t,n){let a=Date.now(),u=t.currentTime-n.lastMediaTime,S=(a-n.lastWallTime)/1e3;u>0&&S>0&&u<=Math.max(3,S+1)&&(n.watchedSeconds+=Math.min(u,S+.5)),n.lastMediaTime=t.currentTime,n.lastWallTime=a}function we(t,n){if(!t.duration)return;let a=Math.min(100,Math.floor(t.currentTime/t.duration*100));for(let u of[25,50,75,100])a>=u&&!n.milestones.has(u)&&(n.milestones.add(u),k("video_progress",ne(t,n,u)))}function He(){T(window,"scroll",()=>{l&&(l.maxScrollPercent=Math.max(l.maxScrollPercent,he()),!z&&l.maxScrollPercent>=90&&(z=!0,k("scroll",{percent:90})))},{passive:!0}),T(document,"focusin",t=>{let n=t.target?.closest("form");n&&!Q.has(n)&&(Q.add(n),k("form_start",{formId:n.id||void 0,formName:n.getAttribute("name")||void 0}))}),T(document,"submit",t=>{let n=t.target;n instanceof HTMLFormElement&&k("form_submitted",{formId:n.id||void 0,formName:n.getAttribute("name")||void 0})}),T(document,"click",t=>{let n=t.target?.closest("a[href]");if(!n)return;let a=n.href,u=n.origin!==location.origin;n.hasAttribute("download")||at.test(a)?k("file_download",{fileName:n.pathname.split("/").pop(),linkDomain:n.hostname||void 0}):(u||/^mailto:|^tel:/i.test(n.getAttribute("href")??""))&&k("click",{linkDomain:n.hostname||void 0,linkType:a.startsWith("mailto:")?"email":a.startsWith("tel:")?"phone":"outbound"})}),T(document,"play",t=>{let n=t.target;if(!(n instanceof HTMLVideoElement))return;let a=L.get(n);a||(a={milestones:new Set,watchedSeconds:0,lastMediaTime:n.currentTime,lastWallTime:Date.now(),started:!1},L.set(n,a)),a.started||(a.started=!0,k("video_start",ne(n,a))),a.lastMediaTime=n.currentTime,a.lastWallTime=Date.now()},!0),T(document,"timeupdate",t=>{let n=t.target;if(!(n instanceof HTMLVideoElement))return;let a=L.get(n);a&&(Se(n,a),we(n,a))},!0),T(document,"ended",t=>{let n=t.target;if(!(n instanceof HTMLVideoElement))return;let a=L.get(n);a&&(Se(n,a),we(n,a),k("video_complete",ne(n,a,100)))},!0),T(document,"visibilitychange",()=>{document.visibilityState==="hidden"?te("hidden"):je()})}function We(t){try{return t.currentSrc?new URL(t.currentSrc).origin+new URL(t.currentSrc).pathname:void 0}catch{return}}function Ee(){if(!(p||E.state==="disabled"||m.analytics!=="granted"))try{let t=!c(r.anonymous),n=G();$e(),Y(),Z(),p=!0,h++,F=location.href,Q=new WeakSet,L=new WeakMap,Ie(),t&&k("first_visit"),(!n||Date.now()-n.lastActivityAt>=Me)&&k("session_start"),He(),Ke(),T(window,"pagehide",()=>{te("pagehide"),W(!0)}),N=window.setInterval(()=>{W()},3e3),M({state:"ready",error:void 0}),window.dispatchEvent(new Event("robot:ready"))}catch(t){re(!1),M({state:"error",error:t instanceof Error?t.message:"Initialization failed"})}}function re(t){p=!1,h++,U?.abort(),U=void 0,$=!1,N!==void 0&&window.clearInterval(N),N=void 0;for(let n of X.splice(0).reverse())n();l=void 0,R=0,D=0,t&&(b=[],g(r.queue),g(r.anonymous),g(r.session))}function ke(t){if(E.state==="disabled")return;let n=JSON.stringify(m)!==JSON.stringify(t),a=p?c(r.anonymous):null;m={...t},o&&d(r.consent,JSON.stringify({...t,analytics:t.analytics==="granted"})),t.analytics!=="granted"?(re(t.analytics==="denied"||!!a),M({state:"waiting_consent",error:void 0}),n&&a&&be(t,a)):(Ee(),n&&p&&be(t,Y()))}return{track:De,setConsent:ke,start:Ee,restoreLegacyConsent:()=>{o&&m.analytics==="unknown"&&w(r.consent)?.analytics===!0&&ke({...w(r.consent),analytics:"granted"})},getStatus:()=>E,subscribe:t=>(v.add(t),()=>{v.delete(t)}),getAnonymousId:()=>p?c(r.anonymous):null,getSessionId:()=>p?Z():null,destroy:()=>{re(!1),m={analytics:"unknown"},M({state:"disabled"}),v.clear()}}}function B({cookieName:e,changeEvent:o="sendermaster:consent-change",grantedValue:s="granted",deniedValue:r="denied",maxAgeDays:i=365}){if(!/^[\w.-]+$/.test(e))throw new Error("Invalid consent cookie name");return{getSnapshot(){if(typeof document>"u")return"unknown";try{let c=document.cookie.split(";").find(g=>g.trim().startsWith(`${e}=`)),d=c?decodeURIComponent(c.trim().slice(e.length+1)):"";return d===s?"granted":d===r?"denied":"unknown"}catch{return"unknown"}},subscribe(c){if(typeof window>"u")return()=>{};let d=()=>c();return window.addEventListener(o,d),window.addEventListener("focus",d),document.addEventListener("visibilitychange",d),()=>{window.removeEventListener(o,d),window.removeEventListener("focus",d),document.removeEventListener("visibilitychange",d)}},setConsent(c){if(typeof document>"u")return;let d=c==="granted"?s:r;document.cookie=`${e}=${c==="unknown"?"":encodeURIComponent(d)}; Path=/; Max-Age=${c==="unknown"?0:Math.max(0,Math.floor(i*86400))}; SameSite=Lax${location.protocol==="https:"?"; Secure":""}`,window.dispatchEvent(new Event(o))}}}var it=Symbol.for("sendermaster.browser.v1");function P(){if(typeof window>"u")return;let e=window;return e[it]||={subscribers:new Set}}function Ne(e,o){let s=P();if(!s)return O;let r={...e,siteKey:e.siteKey?.trim()||"",apiHost:(e.apiHost||"https://api.sendermaster.com").replace(/\/$/,""),enabled:e.enabled!==!1},i=JSON.stringify(r);if(s.client&&s.fingerprint===i)return s.client.getStatus();s.client?.destroy(),s.fingerprint=i,s.client=qe(r,o),s.client.subscribe(()=>{for(let c of s.subscribers)try{c()}catch{}});for(let c of s.subscribers)try{c()}catch{}return s.client.getStatus()}var I={init:e=>Ne(e,!1),setConsent:e=>P()?.client?.setConsent(e),track(e,o){return P()?.client?.track(e,o)??{queued:!1,reason:"disabled"}},async trackAfterSuccess(e,o){let s=P()?.client,r=s?.getAnonymousId(),i=!!r&&s?.getStatus().consent==="granted",c=await e();if(i&&P()?.client===s&&s?.getAnonymousId()===r&&s.getStatus().consent==="granted")try{let d=o(c);for(let g of Array.isArray(d)?d:[d])I.track(g.name,g.properties)}catch{}return c},trackSearch(e,o={}){let s=e.trim();return!s||s.length>500||o.filterPersonalData!==!1&&/@|(?:\d[\s()+-]*){7,}/.test(s)?{queued:!1,reason:"invalid_event",message:"Search is empty, too long or contains personal data"}:I.track("search",{query:s,...o.custom?{custom:o.custom}:{}})},getStatus:()=>P()?.client?.getStatus()??O,subscribe(e){let o=P();return o?(o.subscribers.add(e),()=>{o.subscribers.delete(e)}):()=>{}},getAnonymousId:()=>P()?.client?.getAnonymousId()??null,getSessionId:()=>P()?.client?.getSessionId()??null,destroy(){let e=P();if(e){e.client?.destroy(),e.client=void 0,e.fingerprint=void 0;for(let o of e.subscribers)try{o()}catch{}}}};function ct(e){Ne(e,!0);let o={start:()=>P()?.client?.start(),track:I.track,setConsent:s=>I.setConsent({...s,analytics:s.analytics?"granted":"denied"}),getAnonymousId:I.getAnonymousId,getSessionId:I.getSessionId};return window.robot=o,P()?.client?.restoreLegacyConsent(),o}function dt(e){if(typeof e!="string"&&typeof e!="number")return;let o=String(e).trim();return o&&o!=="0"&&o.length<=256?o:void 0}function ut(e){if(e==null||e===""||typeof e=="boolean")return;let o=Number(e);return Number.isFinite(o)&&o>=0?o:void 0}var x=require("react/jsx-runtime"),pe=(0,f.createContext)(null),ue=0,le=0;function lt({children:e,analyticsConsent:o,consentAdapter:s,marketingConsent:r=!1,consentSource:i="react",policyVersion:c,...d}){let g=JSON.stringify(d),w=(0,f.useMemo)(()=>B({cookieName:`sendermaster_consent_${Array.from(d.siteKey||"").map(m=>m.charCodeAt(0).toString(16)).join("_")||"default"}`}),[d.siteKey]),v=o===void 0?s??w:void 0;return(0,f.useEffect)(()=>(ue++,le++,()=>{ue--;let m=++le;queueMicrotask(()=>{!ue&&m===le&&I.destroy()})}),[]),(0,f.useEffect)(()=>{I.init(JSON.parse(g));let m=()=>{let E=o??"unknown";try{v&&(E=v.getSnapshot())}catch{}I.setConsent({analytics:E,marketing:r,source:i,policyVersion:c})};return m(),v?.subscribe(m)},[g,v,o,r,i,c]),(0,x.jsx)(pe.Provider,{value:{adapter:v},children:e})}function fe(){let e=(0,f.useSyncExternalStore)(I.subscribe,I.getStatus,()=>O);return{...I,status:e}}function Ve(e,o,s,r,i){let c=(0,f.useContext)(pe),{status:d}=fe(),g=(0,f.useRef)(""),w=i?d.pageViewId:"",v=JSON.stringify(o);(0,f.useEffect)(()=>{if(!r){g.current="";return}if(!c||d.state!=="ready"||!s||!o)return;let m=`${w}:${s}`;g.current!==m&&I.track(e,o).queued&&(g.current=m)},[c,d.state,w,s,r,v])}function pt(e,{viewKey:o="",active:s=!0}={}){Ve("product_view",e,`${o}:${e?.productId??e?.catalogProductId??""}:${e?.variantId??e?.catalogVariantId??""}`,s,!0)}function ft(e,{checkoutKey:o,active:s=!0}={}){let{status:r}=fe(),[i,c]=(0,f.useState)(""),d=(0,f.useRef)("");(0,f.useEffect)(()=>{d.current||=crypto.randomUUID(),c(d.current)},[]);let g=o||e?.checkoutId||(i&&r.pageViewId?`${i}:${r.pageViewId}`:""),w=e&&g?{...e,checkoutId:e.checkoutId||g}:null;Ve("begin_checkout",w,g,s,!1)}function gt({privacyPolicyUrl:e,labels:o,className:s,style:r}){let c=(0,f.useContext)(pe)?.adapter,d=()=>()=>{},g=(0,f.useSyncExternalStore)(c?.subscribe??d,c?.getSnapshot??(()=>"unknown"),()=>"unknown"),[w,v]=(0,f.useState)(!1),[m,E]=(0,f.useState)(!1);if((0,f.useEffect)(()=>{v(!0)},[]),!w||!c?.setConsent)return null;let p=$=>{c.setConsent?.($),E(!1)},h={message:"With your permission, analytics cookies help us understand how you use this website.",accept:"Accept",reject:"Reject",settings:"Cookie settings",privacyPolicy:"Privacy policy",...o},N={padding:"8px 14px",border:"1px solid #777",borderRadius:4,background:"#fff",color:"#222",cursor:"pointer",font:"inherit"};return(0,x.jsx)("div",{className:s,style:{position:"fixed",bottom:12,left:12,right:g==="unknown"||m?12:void 0,zIndex:1e3,...r},children:g==="unknown"||m?(0,x.jsxs)("section",{role:"region","aria-label":"Cookie preferences",style:{padding:16,background:"#fff",color:"#222",border:"1px solid #ccc",borderRadius:6,font:"14px/1.5 sans-serif"},children:[(0,x.jsxs)("p",{children:[h.message," ",e&&(0,x.jsx)("a",{href:e,children:h.privacyPolicy})]}),(0,x.jsxs)("div",{style:{display:"flex",flexWrap:"wrap",gap:8},children:[(0,x.jsx)("button",{type:"button",style:N,onClick:()=>p("granted"),children:h.accept}),(0,x.jsx)("button",{type:"button",style:N,onClick:()=>p("denied"),children:h.reject})]})]}):(0,x.jsx)("button",{type:"button",style:N,onClick:()=>E(!0),children:h.settings})})}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './types/react/src/index';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use client";import{createContext as at,useContext as Ve,useEffect as K,useMemo as it,useRef as $e,useState as pe,useSyncExternalStore as Re}from"react";var Qe={product_view:[{name:"catalogProductId",type:"string",required:!1,constraint:"1\u2013100; current-site catalog ID"},{name:"catalogVariantId",type:"string",required:!1,constraint:"1\u2013100; requires catalogProductId"},{name:"productId",type:"string",required:!1,constraint:"1\u2013256; required unless catalogProductId is provided"},{name:"variantId",type:"string",required:!1,constraint:"1\u2013256"},{name:"amount",type:"number",required:!1,constraint:"\u2265 0; requires currency"},{name:"currency",type:"string",required:!1,constraint:"3 uppercase letters; requires amount"},{name:"custom",type:"object",required:!1,constraint:"\u2264 50 fields / 3 levels / 16 KB"}],add_to_cart:[{name:"catalogProductId",type:"string",required:!1,constraint:"1\u2013100; current-site catalog ID"},{name:"catalogVariantId",type:"string",required:!1,constraint:"1\u2013100; requires catalogProductId"},{name:"productId",type:"string",required:!1,constraint:"1\u2013256; required unless catalogProductId is provided"},{name:"quantity",type:"integer",required:!0,constraint:"\u2265 1"},{name:"variantId",type:"string",required:!1,constraint:"1\u2013256"},{name:"amount",type:"number",required:!1,constraint:"\u2265 0; requires currency"},{name:"currency",type:"string",required:!1,constraint:"3 uppercase letters; requires amount"},{name:"custom",type:"object",required:!1,constraint:"\u2264 50 fields / 3 levels / 16 KB"}],begin_checkout:[{name:"checkoutId",type:"string",required:!0,constraint:"1\u2013256"},{name:"items",type:"array",required:!0,constraint:"1\u2013100 items"},{name:"amount",type:"number",required:!0,constraint:"\u2265 0"},{name:"currency",type:"string",required:!0,constraint:"3 uppercase letters"},{name:"custom",type:"object",required:!1,constraint:"\u2264 50 fields / 3 levels / 16 KB"}],search:[{name:"query",type:"string",required:!0,constraint:"1\u2013500"},{name:"resultsCount",type:"integer",required:!1,constraint:"\u2265 0"},{name:"custom",type:"object",required:!1,constraint:"\u2264 50 fields / 3 levels / 16 KB"}],wishlist_added:[{name:"catalogProductId",type:"string",required:!1,constraint:"1\u2013100; current-site catalog ID"},{name:"catalogVariantId",type:"string",required:!1,constraint:"1\u2013100; requires catalogProductId"},{name:"productId",type:"string",required:!1,constraint:"1\u2013256; required unless catalogProductId is provided"},{name:"listName",type:"string",required:!1,constraint:"1\u2013256"},{name:"custom",type:"object",required:!1,constraint:"\u2264 50 fields / 3 levels / 16 KB"}]},Xe=[{name:"catalogProductId",type:"string",required:!1,constraint:"1\u2013100; current-site catalog ID"},{name:"catalogVariantId",type:"string",required:!1,constraint:"1\u2013100; requires catalogProductId"},{name:"productId",type:"string",required:!1,constraint:"1\u2013256; required unless catalogProductId is provided"},{name:"quantity",type:"integer",required:!0,constraint:"\u2265 1"},{name:"variantId",type:"string",required:!1,constraint:"1\u2013256"},{name:"amount",type:"number",required:!1,constraint:"\u2265 0"}],q=256,Ye=500,Ce=100,Ae=50,_e=3,Pe=16*1024,Ge=/(password|passcode|secret|token|api.?key|card.?number|cvv|cvc|security.?code|ssn|passport)/i,Ze=Object.fromEntries(Object.entries(Qe).map(([t,o])=>[t,o.map(s=>s.name)]));function et(t,o){let s=[];if(!J(o))return[{path:"properties",message:"must be an object"}];let r=o;for(let d of Object.keys(r))Ze[t].includes(d)||s.push({path:`properties.${d}`,message:"is not a supported standard field; place extension data under custom"});return t==="wishlist_added"?(A(r,"productId",s,!r.catalogProductId,q),A(r,"listName",s,!1,q)):t==="product_view"||t==="add_to_cart"?(A(r,"productId",s,!r.catalogProductId,q),A(r,"variantId",s,!1,q),ae(r,"amount",s,!1,!1),xe(r,s,!1),r.amount===void 0!=(r.currency===void 0)&&s.push({path:"properties.amount",message:"amount and currency must be provided together"}),t==="add_to_cart"&&ie(r,"quantity",s,!0,1)):t==="begin_checkout"?(A(r,"checkoutId",s,!0,q),ae(r,"amount",s,!0,!1),xe(r,s,!0),!Array.isArray(r.items)||r.items.length<1||r.items.length>Ce?s.push({path:"properties.items",message:`must contain 1-${Ce} items`}):r.items.forEach((d,i)=>tt(d,i,s))):(A(r,"query",s,!0,Ye),ie(r,"resultsCount",s,!1,0)),["product_view","add_to_cart","wishlist_added"].includes(t)&&(A(r,"catalogProductId",s,!1,100),A(r,"catalogVariantId",s,!1,100),r.catalogVariantId&&!r.catalogProductId&&s.push({path:"properties.catalogVariantId",message:"requires catalogProductId"})),r.custom!==void 0&&nt(r.custom,s),s}function Te(t,o){let s=et(t,o);if(s.length)throw new se(t,s);let r=o,d={};for(let i of["variantId","quantity","checkoutId","items","query","resultsCount","listName","custom"])r[i]!==void 0&&(d[i]=r[i]);return{...typeof r.productId=="string"?{productId:r.productId}:{},...typeof r.catalogProductId=="string"?{catalogProductId:r.catalogProductId}:{},...typeof r.catalogVariantId=="string"?{catalogVariantId:r.catalogVariantId}:{},...typeof r.amount=="number"?{amount:r.amount}:{},...typeof r.currency=="string"?{currency:r.currency}:{},properties:d}}var se=class extends Error{constructor(s,r){super(`Invalid ${s} event: ${r.map(d=>`${d.path} ${d.message}`).join("; ")}`);this.eventName=s;this.issues=r;this.name="StandardEventValidationError"}eventName;issues};function tt(t,o,s){let r=`properties.items[${o}]`;if(!J(t)){s.push({path:r,message:"must be an object"});return}let d=t,i=Xe.map(c=>c.name);for(let c of Object.keys(d))i.includes(c)||s.push({path:`${r}.${c}`,message:"is not supported"});A(d,"productId",s,!d.catalogProductId,q,r),A(d,"catalogProductId",s,!1,100,r),A(d,"catalogVariantId",s,!1,100,r),d.catalogVariantId&&!d.catalogProductId&&s.push({path:`${r}.catalogVariantId`,message:"requires catalogProductId"}),A(d,"variantId",s,!1,q,r),ie(d,"quantity",s,!0,1,r),ae(d,"amount",s,!1,!1,r)}function nt(t,o){if(!J(t)){o.push({path:"properties.custom",message:"must be an object"});return}let s=t;Object.keys(s).length>Ae&&o.push({path:"properties.custom",message:`must contain at most ${Ae} top-level fields`}),oe(s,"properties.custom",1,o,new WeakSet);try{new TextEncoder().encode(JSON.stringify(s)).length>Pe&&o.push({path:"properties.custom",message:`must be at most ${Pe} bytes`})}catch{o.push({path:"properties.custom",message:"must be valid JSON data"})}}function oe(t,o,s,r,d){if(s>_e){r.push({path:o,message:`must not exceed ${_e} levels`});return}if(!(t===null||typeof t=="string"||typeof t=="boolean"||typeof t=="number"&&Number.isFinite(t))){if(typeof t=="object"&&t){if(d.has(t)){r.push({path:o,message:"must not contain circular references"});return}d.add(t)}if(Array.isArray(t)){t.forEach((i,c)=>oe(i,`${o}[${c}]`,s+1,r,d));return}if(J(t)){Object.entries(t).forEach(([i,c])=>{(i.startsWith("_")||i.toLowerCase().startsWith("sm_"))&&r.push({path:`${o}.${i}`,message:"uses a reserved prefix"}),Ge.test(i)&&r.push({path:`${o}.${i}`,message:"must not contain secrets or sensitive payment/identity data"}),oe(c,`${o}.${i}`,s+1,r,d)});return}r.push({path:o,message:"must contain JSON-compatible values only"})}}function J(t){if(!t||typeof t!="object"||Array.isArray(t))return!1;let o=Object.getPrototypeOf(t);return o===Object.prototype||o===null}function A(t,o,s,r,d,i="properties"){let c=t[o];if(c===void 0){r&&s.push({path:`${i}.${o}`,message:"is required"});return}(typeof c!="string"||c.length<1||c.length>d)&&s.push({path:`${i}.${o}`,message:`must be a string with 1-${d} characters`})}function ae(t,o,s,r,d,i="properties"){let c=t[o];if(c===void 0){r&&s.push({path:`${i}.${o}`,message:"is required"});return}(typeof c!="number"||!Number.isFinite(c)||(d?c<=0:c<0))&&s.push({path:`${i}.${o}`,message:d?"must be a positive finite number":"must be a non-negative finite number"})}function ie(t,o,s,r,d,i="properties"){let c=t[o];if(c===void 0){r&&s.push({path:`${i}.${o}`,message:"is required"});return}(typeof c!="number"||!Number.isInteger(c)||c<d)&&s.push({path:`${i}.${o}`,message:`must be an integer greater than or equal to ${d}`})}function xe(t,o,s){let r=t.currency;if(r===void 0){s&&o.push({path:"properties.currency",message:"is required"});return}(typeof r!="string"||!/^[A-Z]{3}$/.test(r))&&o.push({path:"properties.currency",message:"must be a 3-letter uppercase currency code"})}var Me=1800*1e3,rt=1440*60*1e3,st=/\.(?:pdf|csv|docx?|xlsx?|pptx?|zip|rar|7z)(?:$|[?#])/i,$=Object.freeze({state:"disabled",consent:"unknown",queueLength:0,pageViewId:null});function qe(t,o=!1){let s=o?"robot_store":`sendermaster:${t.siteKey}`,r={anonymous:`${s}_anonymous_id`,session:`${s}_session`,consent:`${s}_consent`,queue:`${s}_event_queue`},d=new Map;function i(e){try{let n=localStorage.getItem(e);return n!==null&&d.set(e,n),n??d.get(e)??null}catch{return d.get(e)??null}}function c(e,n){d.set(e,n);try{localStorage.setItem(e,n)}catch{}}function f(e){d.delete(e);try{localStorage.removeItem(e)}catch{}}function S(e){try{return JSON.parse(i(e)??"null")}catch{return null}}let b=new Set,g={analytics:"unknown"},w={...$,state:t.enabled===!1||!t.siteKey?"disabled":"waiting_consent"},p=!1,y=0,M,N=!1,U,V=0,O=0,l,B=!1,z=location.href,F=new WeakSet,D=new WeakMap,h=[],Q=[];function x(e={}){let n={...w,consent:g.analytics,queueLength:h.length,pageViewId:l?.id??null,...e};if(JSON.stringify(n)!==JSON.stringify(w)){w=Object.freeze(n);for(let a of b)try{a()}catch{}}}function P(e,n,a,u){let I=y,C=T=>{if(p&&y===I)try{a(T)}catch{}};e.addEventListener(n,C,u),Q.push(()=>e.removeEventListener(n,C,u))}function ge(){return(t.apiHost??"https://api.sendermaster.com").replace(/\/$/,"")}function X(){let e=i(r.anonymous);return e||(e=crypto.randomUUID(),c(r.anonymous,e)),e}function Y(){let e=S(r.session);return e&&typeof e.id=="string"&&typeof e.lastActivityAt=="number"?e:void 0}function G(){let e=Date.now(),n=Y();if(!n||e-n.lastActivityAt>=Me){let a={id:crypto.randomUUID(),lastActivityAt:e};return c(r.session,JSON.stringify(a)),a.id}return n.lastActivityAt=e,c(r.session,JSON.stringify(n)),n.id}function Z(){let e=Date.now();h=h.filter(n=>n.siteKey===t.siteKey&&e-Date.parse(n.event.occurredAt)<rt&&Date.parse(n.event.occurredAt)<=e+6e4).slice(-100)}function H(){Z(),c(r.queue,JSON.stringify(h)),x()}function Le(){let e=S(r.queue);Array.isArray(e)&&(h=e.flatMap(n=>{if(n?.event?.eventId&&typeof n.anonymousId=="string"&&typeof n.sessionId=="string")return[n];let a=i(r.anonymous),u=Y();return o&&n?.eventId&&a&&u?[{siteKey:t.siteKey,anonymousId:a,sessionId:u.id,event:n}]:[]}),Z())}function me(e){let n=new URL(e);return["email","token","password","access_token"].forEach(a=>n.searchParams.delete(a)),n.toString()}function ye(e){try{return new URL(e).origin}catch{return}}function je(){return{title:document.title.slice(0,512),language:navigator.language,screen:{width:screen.width,height:screen.height},utm:Object.fromEntries(["utm_source","utm_medium","utm_campaign"].flatMap(e=>{let n=new URL(location.href).searchParams.get(e);return n?[[e,n]]:[]}))}}function Ke(e=location.pathname){return t.pageRules?.find(n=>e.startsWith(n.pathPrefix))?.pageType}function he(){let e=document.documentElement.scrollHeight-innerHeight;return e>0?Math.min(100,Math.max(0,Math.round(scrollY/e*100))):0}function E(e,n={},a={}){if(!p)return;let{productId:u,catalogProductId:I,catalogVariantId:C,amount:T,currency:m,pageType:L,...j}=n,k={eventId:crypto.randomUUID(),name:e,occurredAt:new Date().toISOString(),url:a.url??me(location.href),path:a.path??location.pathname,...ye(document.referrer)?{referrer:ye(document.referrer)}:{},...typeof u=="string"?{productId:u}:{},...typeof I=="string"?{catalogProductId:I}:{},...typeof C=="string"?{catalogVariantId:C}:{},...typeof T=="number"?{amount:T}:{},...typeof m=="string"?{currency:m}:{},pageType:a.pageType??(typeof L=="string"?L:l?.pageType),pageViewId:a.pageViewId??l?.id,...a.engagedTimeMsec?{engagedTimeMsec:a.engagedTimeMsec}:{},...Object.keys(j).length?{properties:j}:{},context:je()};return h.push({siteKey:t.siteKey,anonymousId:X(),sessionId:G(),event:JSON.parse(JSON.stringify(k))}),H(),h.length>=20&&W(),k.eventId}function Ue(e,n){if(w.state==="disabled")return{queued:!1,reason:"disabled"};if(g.analytics!=="granted")return{queued:!1,reason:"consent_required"};if(!p)return{queued:!1,reason:"unavailable"};try{let a=Te(e,n),u=E(e,{...a.properties,productId:a.productId,catalogProductId:a.catalogProductId,catalogVariantId:a.catalogVariantId,amount:a.amount,currency:a.currency});return u?{queued:!0,eventId:u}:{queued:!1,reason:"unavailable"}}catch(a){return{queued:!1,reason:"invalid_event",message:a instanceof Error?a.message:"Invalid event"}}}async function W(e=!1){if(!p||N||(Z(),x(),!h.length||!e&&Date.now()<V))return;let n=h[0],a=h.filter(m=>m.siteKey===n.siteKey&&m.anonymousId===n.anonymousId&&m.sessionId===n.sessionId).slice(0,20),u=JSON.stringify({siteKey:n.siteKey,anonymousId:n.anonymousId,sessionId:n.sessionId,events:a.map(m=>m.event)}),I=`${ge()}/v2/collect/events`;if(e)try{if(navigator.sendBeacon?.(I,new Blob([u],{type:"application/json"}))){H();return}}catch{}N=!0;let C=y,T=new AbortController;U=T;try{let m=await fetch(I,{method:"POST",headers:{"content-type":"application/json"},body:u,keepalive:!0,signal:T.signal});if(C!==y||!p)return;if(!m.ok){if(m.status===429||m.status>=500)throw new Error(`Collect HTTP ${m.status}`);let k=new Set(a.map(re=>re.event.eventId));h=h.filter(re=>!k.has(re.event.eventId)),H(),x({state:"error",error:`Collect HTTP ${m.status}: batch discarded`}),V=0,O=0;return}let L=await m.json();if(!Array.isArray(L.results))throw new Error("Collect response missing results");let j=new Set(L.results.filter(k=>k.status==="accepted"||k.status==="duplicate").map(k=>k.eventId));if(!a.every(k=>j.has(k.event.eventId)))throw new Error("Collect response incomplete");if(C!==y||!p)return;h=h.filter(k=>!j.has(k.event.eventId)),O=0,V=0,H(),x({state:"ready",error:void 0,lastDeliveredAt:new Date().toISOString()})}catch(m){if(C!==y||!p)return;O++,V=Date.now()+Math.min(6e4,3e3*2**Math.min(O-1,5)),x({error:m instanceof Error?m.message:"Collect unavailable"})}finally{C===y&&(N=!1,U=void 0)}p&&h.length&&!V&&W()}function be(e,n){let a=JSON.stringify({siteKey:t.siteKey,anonymousId:n,analyticsAllowed:e.analytics==="granted",marketingAllowed:e.marketing??!1,source:e.source??"sdk",policyVersion:e.policyVersion});try{fetch(`${ge()}/v2/collect/consent`,{method:"POST",headers:{"content-type":"application/json"},body:a,keepalive:!0}).then(u=>{if(!u.ok)throw new Error(`Consent HTTP ${u.status}`)}).catch(()=>{})}catch{}}function Ie(){l={id:crypto.randomUUID(),url:me(location.href),path:location.pathname,pageType:Ke(),enteredAt:new Date().toISOString(),visibleAt:document.visibilityState==="visible"?Date.now():0,activeMsec:0,reportedMsec:0,maxScrollPercent:he()},B=!1,E("page_view")}function He(){!p||!l?.visibleAt||(l.activeMsec+=Date.now()-l.visibleAt,l.visibleAt=0)}function ee(e){if(!p||!l)return;He();let n=l.activeMsec-l.reportedMsec;n<1e3||(l.reportedMsec=l.activeMsec,E("page_engagement",{pageViewId:l.id,maxScrollPercent:l.maxScrollPercent,enteredAt:l.enteredAt,exitReason:e},{pageType:l.pageType,pageViewId:l.id,engagedTimeMsec:n,url:l.url,path:l.path}))}function We(){p&&l&&!l.visibleAt&&(l.visibleAt=Date.now())}function ve(){!p||location.href===z||(ee("navigation"),z=location.href,Ie())}function Je(){let e=y,n=a=>{let u=history[a];history[a]=function(...C){let T=u.apply(this,C);return queueMicrotask(()=>{p&&y===e&&ve()}),T};let I=history[a];Q.push(()=>{history[a]===I&&(history[a]=u)})};n("pushState"),n("replaceState"),P(window,"popstate",ve)}function Be(e){let n=Fe(e),a=Array.from(document.querySelectorAll("video")).indexOf(e);return{videoId:e.dataset.robotVideoId||e.id||n||`video:${location.pathname}:${a}`,videoTitle:e.dataset.robotVideoTitle||e.getAttribute("title")||void 0,productId:e.dataset.robotProductId||void 0,videoSrc:n}}function te(e,n,a){return{...Be(e),watchedSeconds:Math.round(n.watchedSeconds*10)/10,durationSeconds:Math.round(e.duration*10)/10,...a!==void 0?{progressPercent:a}:{}}}function Se(e,n){let a=Date.now(),u=e.currentTime-n.lastMediaTime,I=(a-n.lastWallTime)/1e3;u>0&&I>0&&u<=Math.max(3,I+1)&&(n.watchedSeconds+=Math.min(u,I+.5)),n.lastMediaTime=e.currentTime,n.lastWallTime=a}function we(e,n){if(!e.duration)return;let a=Math.min(100,Math.floor(e.currentTime/e.duration*100));for(let u of[25,50,75,100])a>=u&&!n.milestones.has(u)&&(n.milestones.add(u),E("video_progress",te(e,n,u)))}function ze(){P(window,"scroll",()=>{l&&(l.maxScrollPercent=Math.max(l.maxScrollPercent,he()),!B&&l.maxScrollPercent>=90&&(B=!0,E("scroll",{percent:90})))},{passive:!0}),P(document,"focusin",e=>{let n=e.target?.closest("form");n&&!F.has(n)&&(F.add(n),E("form_start",{formId:n.id||void 0,formName:n.getAttribute("name")||void 0}))}),P(document,"submit",e=>{let n=e.target;n instanceof HTMLFormElement&&E("form_submitted",{formId:n.id||void 0,formName:n.getAttribute("name")||void 0})}),P(document,"click",e=>{let n=e.target?.closest("a[href]");if(!n)return;let a=n.href,u=n.origin!==location.origin;n.hasAttribute("download")||st.test(a)?E("file_download",{fileName:n.pathname.split("/").pop(),linkDomain:n.hostname||void 0}):(u||/^mailto:|^tel:/i.test(n.getAttribute("href")??""))&&E("click",{linkDomain:n.hostname||void 0,linkType:a.startsWith("mailto:")?"email":a.startsWith("tel:")?"phone":"outbound"})}),P(document,"play",e=>{let n=e.target;if(!(n instanceof HTMLVideoElement))return;let a=D.get(n);a||(a={milestones:new Set,watchedSeconds:0,lastMediaTime:n.currentTime,lastWallTime:Date.now(),started:!1},D.set(n,a)),a.started||(a.started=!0,E("video_start",te(n,a))),a.lastMediaTime=n.currentTime,a.lastWallTime=Date.now()},!0),P(document,"timeupdate",e=>{let n=e.target;if(!(n instanceof HTMLVideoElement))return;let a=D.get(n);a&&(Se(n,a),we(n,a))},!0),P(document,"ended",e=>{let n=e.target;if(!(n instanceof HTMLVideoElement))return;let a=D.get(n);a&&(Se(n,a),we(n,a),E("video_complete",te(n,a,100)))},!0),P(document,"visibilitychange",()=>{document.visibilityState==="hidden"?ee("hidden"):We()})}function Fe(e){try{return e.currentSrc?new URL(e.currentSrc).origin+new URL(e.currentSrc).pathname:void 0}catch{return}}function Ee(){if(!(p||w.state==="disabled"||g.analytics!=="granted"))try{let e=!i(r.anonymous),n=Y();Le(),X(),G(),p=!0,y++,z=location.href,F=new WeakSet,D=new WeakMap,Ie(),e&&E("first_visit"),(!n||Date.now()-n.lastActivityAt>=Me)&&E("session_start"),ze(),Je(),P(window,"pagehide",()=>{ee("pagehide"),W(!0)}),M=window.setInterval(()=>{W()},3e3),x({state:"ready",error:void 0}),window.dispatchEvent(new Event("robot:ready"))}catch(e){ne(!1),x({state:"error",error:e instanceof Error?e.message:"Initialization failed"})}}function ne(e){p=!1,y++,U?.abort(),U=void 0,N=!1,M!==void 0&&window.clearInterval(M),M=void 0;for(let n of Q.splice(0).reverse())n();l=void 0,V=0,O=0,e&&(h=[],f(r.queue),f(r.anonymous),f(r.session))}function ke(e){if(w.state==="disabled")return;let n=JSON.stringify(g)!==JSON.stringify(e),a=p?i(r.anonymous):null;g={...e},o&&c(r.consent,JSON.stringify({...e,analytics:e.analytics==="granted"})),e.analytics!=="granted"?(ne(e.analytics==="denied"||!!a),x({state:"waiting_consent",error:void 0}),n&&a&&be(e,a)):(Ee(),n&&p&&be(e,X()))}return{track:Ue,setConsent:ke,start:Ee,restoreLegacyConsent:()=>{o&&g.analytics==="unknown"&&S(r.consent)?.analytics===!0&&ke({...S(r.consent),analytics:"granted"})},getStatus:()=>w,subscribe:e=>(b.add(e),()=>{b.delete(e)}),getAnonymousId:()=>p?i(r.anonymous):null,getSessionId:()=>p?G():null,destroy:()=>{ne(!1),g={analytics:"unknown"},x({state:"disabled"}),b.clear()}}}function ce({cookieName:t,changeEvent:o="sendermaster:consent-change",grantedValue:s="granted",deniedValue:r="denied",maxAgeDays:d=365}){if(!/^[\w.-]+$/.test(t))throw new Error("Invalid consent cookie name");return{getSnapshot(){if(typeof document>"u")return"unknown";try{let i=document.cookie.split(";").find(f=>f.trim().startsWith(`${t}=`)),c=i?decodeURIComponent(i.trim().slice(t.length+1)):"";return c===s?"granted":c===r?"denied":"unknown"}catch{return"unknown"}},subscribe(i){if(typeof window>"u")return()=>{};let c=()=>i();return window.addEventListener(o,c),window.addEventListener("focus",c),document.addEventListener("visibilitychange",c),()=>{window.removeEventListener(o,c),window.removeEventListener("focus",c),document.removeEventListener("visibilitychange",c)}},setConsent(i){if(typeof document>"u")return;let c=i==="granted"?s:r;document.cookie=`${t}=${i==="unknown"?"":encodeURIComponent(c)}; Path=/; Max-Age=${i==="unknown"?0:Math.max(0,Math.floor(d*86400))}; SameSite=Lax${location.protocol==="https:"?"; Secure":""}`,window.dispatchEvent(new Event(o))}}}var ot=Symbol.for("sendermaster.browser.v1");function _(){if(typeof window>"u")return;let t=window;return t[ot]||={subscribers:new Set}}function Ne(t,o){let s=_();if(!s)return $;let r={...t,siteKey:t.siteKey?.trim()||"",apiHost:(t.apiHost||"https://api.sendermaster.com").replace(/\/$/,""),enabled:t.enabled!==!1},d=JSON.stringify(r);if(s.client&&s.fingerprint===d)return s.client.getStatus();s.client?.destroy(),s.fingerprint=d,s.client=qe(r,o),s.client.subscribe(()=>{for(let i of s.subscribers)try{i()}catch{}});for(let i of s.subscribers)try{i()}catch{}return s.client.getStatus()}var v={init:t=>Ne(t,!1),setConsent:t=>_()?.client?.setConsent(t),track(t,o){return _()?.client?.track(t,o)??{queued:!1,reason:"disabled"}},async trackAfterSuccess(t,o){let s=_()?.client,r=s?.getAnonymousId(),d=!!r&&s?.getStatus().consent==="granted",i=await t();if(d&&_()?.client===s&&s?.getAnonymousId()===r&&s.getStatus().consent==="granted")try{let c=o(i);for(let f of Array.isArray(c)?c:[c])v.track(f.name,f.properties)}catch{}return i},trackSearch(t,o={}){let s=t.trim();return!s||s.length>500||o.filterPersonalData!==!1&&/@|(?:\d[\s()+-]*){7,}/.test(s)?{queued:!1,reason:"invalid_event",message:"Search is empty, too long or contains personal data"}:v.track("search",{query:s,...o.custom?{custom:o.custom}:{}})},getStatus:()=>_()?.client?.getStatus()??$,subscribe(t){let o=_();return o?(o.subscribers.add(t),()=>{o.subscribers.delete(t)}):()=>{}},getAnonymousId:()=>_()?.client?.getAnonymousId()??null,getSessionId:()=>_()?.client?.getSessionId()??null,destroy(){let t=_();if(t){t.client?.destroy(),t.client=void 0,t.fingerprint=void 0;for(let o of t.subscribers)try{o()}catch{}}}};function gt(t){Ne(t,!0);let o={start:()=>_()?.client?.start(),track:v.track,setConsent:s=>v.setConsent({...s,analytics:s.analytics?"granted":"denied"}),getAnonymousId:v.getAnonymousId,getSessionId:v.getSessionId};return window.robot=o,_()?.client?.restoreLegacyConsent(),o}function mt(t){if(typeof t!="string"&&typeof t!="number")return;let o=String(t).trim();return o&&o!=="0"&&o.length<=256?o:void 0}function yt(t){if(t==null||t===""||typeof t=="boolean")return;let o=Number(t);return Number.isFinite(o)&&o>=0?o:void 0}import{jsx as R,jsxs as le}from"react/jsx-runtime";var fe=at(null),de=0,ue=0;function wt({children:t,analyticsConsent:o,consentAdapter:s,marketingConsent:r=!1,consentSource:d="react",policyVersion:i,...c}){let f=JSON.stringify(c),S=it(()=>ce({cookieName:`sendermaster_consent_${Array.from(c.siteKey||"").map(g=>g.charCodeAt(0).toString(16)).join("_")||"default"}`}),[c.siteKey]),b=o===void 0?s??S:void 0;return K(()=>(de++,ue++,()=>{de--;let g=++ue;queueMicrotask(()=>{!de&&g===ue&&v.destroy()})}),[]),K(()=>{v.init(JSON.parse(f));let g=()=>{let w=o??"unknown";try{b&&(w=b.getSnapshot())}catch{}v.setConsent({analytics:w,marketing:r,source:d,policyVersion:i})};return g(),b?.subscribe(g)},[f,b,o,r,d,i]),R(fe.Provider,{value:{adapter:b},children:t})}function Oe(){let t=Re(v.subscribe,v.getStatus,()=>$);return{...v,status:t}}function De(t,o,s,r,d){let i=Ve(fe),{status:c}=Oe(),f=$e(""),S=d?c.pageViewId:"",b=JSON.stringify(o);K(()=>{if(!r){f.current="";return}if(!i||c.state!=="ready"||!s||!o)return;let g=`${S}:${s}`;f.current!==g&&v.track(t,o).queued&&(f.current=g)},[i,c.state,S,s,r,b])}function Et(t,{viewKey:o="",active:s=!0}={}){De("product_view",t,`${o}:${t?.productId??t?.catalogProductId??""}:${t?.variantId??t?.catalogVariantId??""}`,s,!0)}function kt(t,{checkoutKey:o,active:s=!0}={}){let{status:r}=Oe(),[d,i]=pe(""),c=$e("");K(()=>{c.current||=crypto.randomUUID(),i(c.current)},[]);let f=o||t?.checkoutId||(d&&r.pageViewId?`${d}:${r.pageViewId}`:""),S=t&&f?{...t,checkoutId:t.checkoutId||f}:null;De("begin_checkout",S,f,s,!1)}function Ct({privacyPolicyUrl:t,labels:o,className:s,style:r}){let i=Ve(fe)?.adapter,c=()=>()=>{},f=Re(i?.subscribe??c,i?.getSnapshot??(()=>"unknown"),()=>"unknown"),[S,b]=pe(!1),[g,w]=pe(!1);if(K(()=>{b(!0)},[]),!S||!i?.setConsent)return null;let p=N=>{i.setConsent?.(N),w(!1)},y={message:"With your permission, analytics cookies help us understand how you use this website.",accept:"Accept",reject:"Reject",settings:"Cookie settings",privacyPolicy:"Privacy policy",...o},M={padding:"8px 14px",border:"1px solid #777",borderRadius:4,background:"#fff",color:"#222",cursor:"pointer",font:"inherit"};return R("div",{className:s,style:{position:"fixed",bottom:12,left:12,right:f==="unknown"||g?12:void 0,zIndex:1e3,...r},children:f==="unknown"||g?le("section",{role:"region","aria-label":"Cookie preferences",style:{padding:16,background:"#fff",color:"#222",border:"1px solid #ccc",borderRadius:6,font:"14px/1.5 sans-serif"},children:[le("p",{children:[y.message," ",t&&R("a",{href:t,children:y.privacyPolicy})]}),le("div",{style:{display:"flex",flexWrap:"wrap",gap:8},children:[R("button",{type:"button",style:M,onClick:()=>p("granted"),children:y.accept}),R("button",{type:"button",style:M,onClick:()=>p("denied"),children:y.reject})]})]}):R("button",{type:"button",style:M,onClick:()=>w(!0),children:y.settings})})}export{Ct as SenderMasterConsentBanner,wt as SenderMasterProvider,ce as createCookieConsentAdapter,gt as installLegacyPixel,v as senderMaster,yt as toAmount,mt as toId,kt as useBeginCheckout,Et as useProductView,Oe as useSenderMaster};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { AnalyticsConsent } from './core';
|
|
2
|
+
export interface ConsentAdapter {
|
|
3
|
+
getSnapshot(): AnalyticsConsent;
|
|
4
|
+
subscribe(listener: () => void): () => void;
|
|
5
|
+
setConsent?(value: AnalyticsConsent): void;
|
|
6
|
+
}
|
|
7
|
+
export type CookieConsentOptions = {
|
|
8
|
+
cookieName: string;
|
|
9
|
+
changeEvent?: string;
|
|
10
|
+
grantedValue?: string;
|
|
11
|
+
deniedValue?: string;
|
|
12
|
+
maxAgeDays?: number;
|
|
13
|
+
};
|
|
14
|
+
/** A bridge for an existing banner; no behavior or identifiers are stored here. */
|
|
15
|
+
export declare function createCookieConsentAdapter({ cookieName, changeEvent, grantedValue, deniedValue, maxAgeDays }: CookieConsentOptions): ConsentAdapter;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { type StandardEventInputMap, type StandardEventName } from '../../event-contracts/src';
|
|
2
|
+
export type { StandardEventInputMap, StandardEventName, CheckoutItem } from '../../event-contracts/src';
|
|
3
|
+
export type AnalyticsConsent = 'unknown' | 'granted' | 'denied';
|
|
4
|
+
export type Consent = {
|
|
5
|
+
analytics: AnalyticsConsent;
|
|
6
|
+
marketing?: boolean;
|
|
7
|
+
source?: string;
|
|
8
|
+
policyVersion?: string;
|
|
9
|
+
};
|
|
10
|
+
export type Config = {
|
|
11
|
+
enabled?: boolean;
|
|
12
|
+
siteKey: string;
|
|
13
|
+
apiHost?: string;
|
|
14
|
+
pageRules?: {
|
|
15
|
+
pathPrefix: string;
|
|
16
|
+
pageType: string;
|
|
17
|
+
}[];
|
|
18
|
+
};
|
|
19
|
+
export type Status = Readonly<{
|
|
20
|
+
state: 'disabled' | 'waiting_consent' | 'ready' | 'error';
|
|
21
|
+
consent: AnalyticsConsent;
|
|
22
|
+
queueLength: number;
|
|
23
|
+
pageViewId: string | null;
|
|
24
|
+
error?: string;
|
|
25
|
+
lastDeliveredAt?: string;
|
|
26
|
+
}>;
|
|
27
|
+
export type TrackResult = {
|
|
28
|
+
queued: true;
|
|
29
|
+
eventId: string;
|
|
30
|
+
} | {
|
|
31
|
+
queued: false;
|
|
32
|
+
reason: 'disabled' | 'consent_required' | 'invalid_event' | 'unavailable';
|
|
33
|
+
message?: string;
|
|
34
|
+
};
|
|
35
|
+
export declare const SERVER_STATUS: Status;
|
|
36
|
+
export declare function createClient(config: Config, legacy?: boolean): {
|
|
37
|
+
track: <Name extends StandardEventName>(name: Name, properties: StandardEventInputMap[Name]) => TrackResult;
|
|
38
|
+
setConsent: (value: Consent) => void;
|
|
39
|
+
start: () => void;
|
|
40
|
+
restoreLegacyConsent: () => void;
|
|
41
|
+
getStatus: () => Readonly<{
|
|
42
|
+
state: "disabled" | "waiting_consent" | "ready" | "error";
|
|
43
|
+
consent: AnalyticsConsent;
|
|
44
|
+
queueLength: number;
|
|
45
|
+
pageViewId: string | null;
|
|
46
|
+
error?: string;
|
|
47
|
+
lastDeliveredAt?: string;
|
|
48
|
+
}>;
|
|
49
|
+
subscribe: (fn: () => void) => () => void;
|
|
50
|
+
getAnonymousId: () => string | null;
|
|
51
|
+
getSessionId: () => string | null;
|
|
52
|
+
destroy: () => void;
|
|
53
|
+
};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { type Config, type Consent, type StandardEventName, type StandardEventInputMap, type TrackResult } from './core';
|
|
2
|
+
export type { Config, Consent, Status, TrackResult, AnalyticsConsent, StandardEventName, StandardEventInputMap, CheckoutItem } from './core';
|
|
3
|
+
export { createCookieConsentAdapter } from './consent';
|
|
4
|
+
export type { ConsentAdapter, CookieConsentOptions } from './consent';
|
|
5
|
+
/** Safe to import during SSR; browser work starts only at init + granted consent. */
|
|
6
|
+
export declare const senderMaster: {
|
|
7
|
+
init: (config: Config) => Readonly<{
|
|
8
|
+
state: "disabled" | "waiting_consent" | "ready" | "error";
|
|
9
|
+
consent: import("./core").AnalyticsConsent;
|
|
10
|
+
queueLength: number;
|
|
11
|
+
pageViewId: string | null;
|
|
12
|
+
error?: string;
|
|
13
|
+
lastDeliveredAt?: string;
|
|
14
|
+
}>;
|
|
15
|
+
setConsent: (value: Consent) => void | undefined;
|
|
16
|
+
track<Name extends StandardEventName>(name: Name, properties: StandardEventInputMap[Name]): TrackResult;
|
|
17
|
+
/** Preserve the business result; never replay actions spanning consent withdrawal or client replacement. */
|
|
18
|
+
trackAfterSuccess<T>(action: () => Promise<T>, events: (result: T) => BusinessEvent | BusinessEvent[]): Promise<T>;
|
|
19
|
+
trackSearch(query: string, options?: {
|
|
20
|
+
custom?: Record<string, unknown>;
|
|
21
|
+
filterPersonalData?: boolean;
|
|
22
|
+
}): TrackResult;
|
|
23
|
+
getStatus: () => Readonly<{
|
|
24
|
+
state: "disabled" | "waiting_consent" | "ready" | "error";
|
|
25
|
+
consent: import("./core").AnalyticsConsent;
|
|
26
|
+
queueLength: number;
|
|
27
|
+
pageViewId: string | null;
|
|
28
|
+
error?: string;
|
|
29
|
+
lastDeliveredAt?: string;
|
|
30
|
+
}>;
|
|
31
|
+
subscribe(fn: () => void): () => void;
|
|
32
|
+
getAnonymousId: () => string | null;
|
|
33
|
+
getSessionId: () => string | null;
|
|
34
|
+
destroy(): void;
|
|
35
|
+
};
|
|
36
|
+
/** Internal compatibility entry; keep the old public methods and storage names. */
|
|
37
|
+
export declare function installLegacyPixel(config: Config): {
|
|
38
|
+
start: () => void | undefined;
|
|
39
|
+
track: <Name extends StandardEventName>(name: Name, properties: StandardEventInputMap[Name]) => TrackResult;
|
|
40
|
+
setConsent: (value: {
|
|
41
|
+
analytics: boolean;
|
|
42
|
+
marketing?: boolean;
|
|
43
|
+
source?: string;
|
|
44
|
+
policyVersion?: string;
|
|
45
|
+
}) => void | undefined;
|
|
46
|
+
getAnonymousId: () => string | null;
|
|
47
|
+
getSessionId: () => string | null;
|
|
48
|
+
};
|
|
49
|
+
export type BusinessEvent = {
|
|
50
|
+
[N in StandardEventName]: {
|
|
51
|
+
name: N;
|
|
52
|
+
properties: StandardEventInputMap[N];
|
|
53
|
+
};
|
|
54
|
+
}[StandardEventName];
|
|
55
|
+
export declare function toId(value: unknown): string | undefined;
|
|
56
|
+
export declare function toAmount(value: unknown): number | undefined;
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
export declare const STANDARD_EVENT_NAMES: readonly ["product_view", "add_to_cart", "begin_checkout", "search", "wishlist_added"];
|
|
2
|
+
export type StandardEventName = (typeof STANDARD_EVENT_NAMES)[number];
|
|
3
|
+
export type CustomProperties = Record<string, unknown>;
|
|
4
|
+
export type CheckoutItem = {
|
|
5
|
+
catalogProductId?: string;
|
|
6
|
+
catalogVariantId?: string;
|
|
7
|
+
productId?: string;
|
|
8
|
+
quantity: number;
|
|
9
|
+
variantId?: string;
|
|
10
|
+
amount?: number;
|
|
11
|
+
};
|
|
12
|
+
export type StandardEventInputMap = {
|
|
13
|
+
product_view: {
|
|
14
|
+
catalogProductId?: string;
|
|
15
|
+
catalogVariantId?: string;
|
|
16
|
+
productId?: string;
|
|
17
|
+
variantId?: string;
|
|
18
|
+
amount?: number;
|
|
19
|
+
currency?: string;
|
|
20
|
+
custom?: CustomProperties;
|
|
21
|
+
};
|
|
22
|
+
add_to_cart: {
|
|
23
|
+
catalogProductId?: string;
|
|
24
|
+
catalogVariantId?: string;
|
|
25
|
+
productId?: string;
|
|
26
|
+
quantity: number;
|
|
27
|
+
variantId?: string;
|
|
28
|
+
amount?: number;
|
|
29
|
+
currency?: string;
|
|
30
|
+
custom?: CustomProperties;
|
|
31
|
+
};
|
|
32
|
+
begin_checkout: {
|
|
33
|
+
checkoutId: string;
|
|
34
|
+
items: CheckoutItem[];
|
|
35
|
+
amount: number;
|
|
36
|
+
currency: string;
|
|
37
|
+
custom?: CustomProperties;
|
|
38
|
+
};
|
|
39
|
+
search: {
|
|
40
|
+
query: string;
|
|
41
|
+
resultsCount?: number;
|
|
42
|
+
custom?: CustomProperties;
|
|
43
|
+
};
|
|
44
|
+
wishlist_added: {
|
|
45
|
+
catalogProductId?: string;
|
|
46
|
+
catalogVariantId?: string;
|
|
47
|
+
productId?: string;
|
|
48
|
+
listName?: string;
|
|
49
|
+
custom?: CustomProperties;
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
export type StandardEventInput = StandardEventInputMap[StandardEventName];
|
|
53
|
+
export type StandardEventIssue = {
|
|
54
|
+
path: string;
|
|
55
|
+
message: string;
|
|
56
|
+
};
|
|
57
|
+
export type NormalizedStandardEvent = {
|
|
58
|
+
productId?: string;
|
|
59
|
+
catalogProductId?: string;
|
|
60
|
+
catalogVariantId?: string;
|
|
61
|
+
amount?: number;
|
|
62
|
+
currency?: string;
|
|
63
|
+
properties: Record<string, unknown>;
|
|
64
|
+
};
|
|
65
|
+
export declare const STANDARD_EVENT_SCHEMAS: {
|
|
66
|
+
readonly product_view: readonly [{
|
|
67
|
+
readonly name: "catalogProductId";
|
|
68
|
+
readonly type: "string";
|
|
69
|
+
readonly required: false;
|
|
70
|
+
readonly constraint: "1–100; current-site catalog ID";
|
|
71
|
+
}, {
|
|
72
|
+
readonly name: "catalogVariantId";
|
|
73
|
+
readonly type: "string";
|
|
74
|
+
readonly required: false;
|
|
75
|
+
readonly constraint: "1–100; requires catalogProductId";
|
|
76
|
+
}, {
|
|
77
|
+
readonly name: "productId";
|
|
78
|
+
readonly type: "string";
|
|
79
|
+
readonly required: false;
|
|
80
|
+
readonly constraint: "1–256; required unless catalogProductId is provided";
|
|
81
|
+
}, {
|
|
82
|
+
readonly name: "variantId";
|
|
83
|
+
readonly type: "string";
|
|
84
|
+
readonly required: false;
|
|
85
|
+
readonly constraint: "1–256";
|
|
86
|
+
}, {
|
|
87
|
+
readonly name: "amount";
|
|
88
|
+
readonly type: "number";
|
|
89
|
+
readonly required: false;
|
|
90
|
+
readonly constraint: "≥ 0; requires currency";
|
|
91
|
+
}, {
|
|
92
|
+
readonly name: "currency";
|
|
93
|
+
readonly type: "string";
|
|
94
|
+
readonly required: false;
|
|
95
|
+
readonly constraint: "3 uppercase letters; requires amount";
|
|
96
|
+
}, {
|
|
97
|
+
readonly name: "custom";
|
|
98
|
+
readonly type: "object";
|
|
99
|
+
readonly required: false;
|
|
100
|
+
readonly constraint: "≤ 50 fields / 3 levels / 16 KB";
|
|
101
|
+
}];
|
|
102
|
+
readonly add_to_cart: readonly [{
|
|
103
|
+
readonly name: "catalogProductId";
|
|
104
|
+
readonly type: "string";
|
|
105
|
+
readonly required: false;
|
|
106
|
+
readonly constraint: "1–100; current-site catalog ID";
|
|
107
|
+
}, {
|
|
108
|
+
readonly name: "catalogVariantId";
|
|
109
|
+
readonly type: "string";
|
|
110
|
+
readonly required: false;
|
|
111
|
+
readonly constraint: "1–100; requires catalogProductId";
|
|
112
|
+
}, {
|
|
113
|
+
readonly name: "productId";
|
|
114
|
+
readonly type: "string";
|
|
115
|
+
readonly required: false;
|
|
116
|
+
readonly constraint: "1–256; required unless catalogProductId is provided";
|
|
117
|
+
}, {
|
|
118
|
+
readonly name: "quantity";
|
|
119
|
+
readonly type: "integer";
|
|
120
|
+
readonly required: true;
|
|
121
|
+
readonly constraint: "≥ 1";
|
|
122
|
+
}, {
|
|
123
|
+
readonly name: "variantId";
|
|
124
|
+
readonly type: "string";
|
|
125
|
+
readonly required: false;
|
|
126
|
+
readonly constraint: "1–256";
|
|
127
|
+
}, {
|
|
128
|
+
readonly name: "amount";
|
|
129
|
+
readonly type: "number";
|
|
130
|
+
readonly required: false;
|
|
131
|
+
readonly constraint: "≥ 0; requires currency";
|
|
132
|
+
}, {
|
|
133
|
+
readonly name: "currency";
|
|
134
|
+
readonly type: "string";
|
|
135
|
+
readonly required: false;
|
|
136
|
+
readonly constraint: "3 uppercase letters; requires amount";
|
|
137
|
+
}, {
|
|
138
|
+
readonly name: "custom";
|
|
139
|
+
readonly type: "object";
|
|
140
|
+
readonly required: false;
|
|
141
|
+
readonly constraint: "≤ 50 fields / 3 levels / 16 KB";
|
|
142
|
+
}];
|
|
143
|
+
readonly begin_checkout: readonly [{
|
|
144
|
+
readonly name: "checkoutId";
|
|
145
|
+
readonly type: "string";
|
|
146
|
+
readonly required: true;
|
|
147
|
+
readonly constraint: "1–256";
|
|
148
|
+
}, {
|
|
149
|
+
readonly name: "items";
|
|
150
|
+
readonly type: "array";
|
|
151
|
+
readonly required: true;
|
|
152
|
+
readonly constraint: "1–100 items";
|
|
153
|
+
}, {
|
|
154
|
+
readonly name: "amount";
|
|
155
|
+
readonly type: "number";
|
|
156
|
+
readonly required: true;
|
|
157
|
+
readonly constraint: "≥ 0";
|
|
158
|
+
}, {
|
|
159
|
+
readonly name: "currency";
|
|
160
|
+
readonly type: "string";
|
|
161
|
+
readonly required: true;
|
|
162
|
+
readonly constraint: "3 uppercase letters";
|
|
163
|
+
}, {
|
|
164
|
+
readonly name: "custom";
|
|
165
|
+
readonly type: "object";
|
|
166
|
+
readonly required: false;
|
|
167
|
+
readonly constraint: "≤ 50 fields / 3 levels / 16 KB";
|
|
168
|
+
}];
|
|
169
|
+
readonly search: readonly [{
|
|
170
|
+
readonly name: "query";
|
|
171
|
+
readonly type: "string";
|
|
172
|
+
readonly required: true;
|
|
173
|
+
readonly constraint: "1–500";
|
|
174
|
+
}, {
|
|
175
|
+
readonly name: "resultsCount";
|
|
176
|
+
readonly type: "integer";
|
|
177
|
+
readonly required: false;
|
|
178
|
+
readonly constraint: "≥ 0";
|
|
179
|
+
}, {
|
|
180
|
+
readonly name: "custom";
|
|
181
|
+
readonly type: "object";
|
|
182
|
+
readonly required: false;
|
|
183
|
+
readonly constraint: "≤ 50 fields / 3 levels / 16 KB";
|
|
184
|
+
}];
|
|
185
|
+
readonly wishlist_added: readonly [{
|
|
186
|
+
readonly name: "catalogProductId";
|
|
187
|
+
readonly type: "string";
|
|
188
|
+
readonly required: false;
|
|
189
|
+
readonly constraint: "1–100; current-site catalog ID";
|
|
190
|
+
}, {
|
|
191
|
+
readonly name: "catalogVariantId";
|
|
192
|
+
readonly type: "string";
|
|
193
|
+
readonly required: false;
|
|
194
|
+
readonly constraint: "1–100; requires catalogProductId";
|
|
195
|
+
}, {
|
|
196
|
+
readonly name: "productId";
|
|
197
|
+
readonly type: "string";
|
|
198
|
+
readonly required: false;
|
|
199
|
+
readonly constraint: "1–256; required unless catalogProductId is provided";
|
|
200
|
+
}, {
|
|
201
|
+
readonly name: "listName";
|
|
202
|
+
readonly type: "string";
|
|
203
|
+
readonly required: false;
|
|
204
|
+
readonly constraint: "1–256";
|
|
205
|
+
}, {
|
|
206
|
+
readonly name: "custom";
|
|
207
|
+
readonly type: "object";
|
|
208
|
+
readonly required: false;
|
|
209
|
+
readonly constraint: "≤ 50 fields / 3 levels / 16 KB";
|
|
210
|
+
}];
|
|
211
|
+
};
|
|
212
|
+
export declare const CHECKOUT_ITEM_SCHEMA: readonly [{
|
|
213
|
+
readonly name: "catalogProductId";
|
|
214
|
+
readonly type: "string";
|
|
215
|
+
readonly required: false;
|
|
216
|
+
readonly constraint: "1–100; current-site catalog ID";
|
|
217
|
+
}, {
|
|
218
|
+
readonly name: "catalogVariantId";
|
|
219
|
+
readonly type: "string";
|
|
220
|
+
readonly required: false;
|
|
221
|
+
readonly constraint: "1–100; requires catalogProductId";
|
|
222
|
+
}, {
|
|
223
|
+
readonly name: "productId";
|
|
224
|
+
readonly type: "string";
|
|
225
|
+
readonly required: false;
|
|
226
|
+
readonly constraint: "1–256; required unless catalogProductId is provided";
|
|
227
|
+
}, {
|
|
228
|
+
readonly name: "quantity";
|
|
229
|
+
readonly type: "integer";
|
|
230
|
+
readonly required: true;
|
|
231
|
+
readonly constraint: "≥ 1";
|
|
232
|
+
}, {
|
|
233
|
+
readonly name: "variantId";
|
|
234
|
+
readonly type: "string";
|
|
235
|
+
readonly required: false;
|
|
236
|
+
readonly constraint: "1–256";
|
|
237
|
+
}, {
|
|
238
|
+
readonly name: "amount";
|
|
239
|
+
readonly type: "number";
|
|
240
|
+
readonly required: false;
|
|
241
|
+
readonly constraint: "≥ 0";
|
|
242
|
+
}];
|
|
243
|
+
export declare function isStandardEventName(name: string): name is StandardEventName;
|
|
244
|
+
export declare function validateStandardEvent(name: StandardEventName, value: unknown): StandardEventIssue[];
|
|
245
|
+
export declare function normalizeStandardEvent(name: StandardEventName, value: unknown): NormalizedStandardEvent;
|
|
246
|
+
export declare class StandardEventValidationError extends Error {
|
|
247
|
+
readonly eventName: StandardEventName;
|
|
248
|
+
readonly issues: StandardEventIssue[];
|
|
249
|
+
constructor(eventName: StandardEventName, issues: StandardEventIssue[]);
|
|
250
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '../../browser/src';
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { type ReactNode, type CSSProperties } from 'react';
|
|
2
|
+
import { type ConsentAdapter, type Config, type AnalyticsConsent, type StandardEventInputMap } from './browser';
|
|
3
|
+
export * from './browser';
|
|
4
|
+
export type SenderMasterProviderProps = Config & {
|
|
5
|
+
children?: ReactNode;
|
|
6
|
+
analyticsConsent?: AnalyticsConsent;
|
|
7
|
+
consentAdapter?: ConsentAdapter;
|
|
8
|
+
marketingConsent?: boolean;
|
|
9
|
+
consentSource?: string;
|
|
10
|
+
policyVersion?: string;
|
|
11
|
+
};
|
|
12
|
+
export declare function SenderMasterProvider({ children, analyticsConsent, consentAdapter, marketingConsent, consentSource, policyVersion, ...config }: SenderMasterProviderProps): import("react").JSX.Element;
|
|
13
|
+
export declare function useSenderMaster(): {
|
|
14
|
+
status: Readonly<{
|
|
15
|
+
state: "disabled" | "waiting_consent" | "ready" | "error";
|
|
16
|
+
consent: AnalyticsConsent;
|
|
17
|
+
queueLength: number;
|
|
18
|
+
pageViewId: string | null;
|
|
19
|
+
error?: string;
|
|
20
|
+
lastDeliveredAt?: string;
|
|
21
|
+
}>;
|
|
22
|
+
init: (config: Config) => Readonly<{
|
|
23
|
+
state: "disabled" | "waiting_consent" | "ready" | "error";
|
|
24
|
+
consent: AnalyticsConsent;
|
|
25
|
+
queueLength: number;
|
|
26
|
+
pageViewId: string | null;
|
|
27
|
+
error?: string;
|
|
28
|
+
lastDeliveredAt?: string;
|
|
29
|
+
}>;
|
|
30
|
+
setConsent: (value: import("./browser").Consent) => void | undefined;
|
|
31
|
+
track<Name extends import("./browser").StandardEventName>(name: Name, properties: StandardEventInputMap[Name]): import("./browser").TrackResult;
|
|
32
|
+
trackAfterSuccess<T>(action: () => Promise<T>, events: (result: T) => import("./browser").BusinessEvent | import("./browser").BusinessEvent[]): Promise<T>;
|
|
33
|
+
trackSearch(query: string, options?: {
|
|
34
|
+
custom?: Record<string, unknown>;
|
|
35
|
+
filterPersonalData?: boolean;
|
|
36
|
+
}): import("./browser").TrackResult;
|
|
37
|
+
getStatus: () => Readonly<{
|
|
38
|
+
state: "disabled" | "waiting_consent" | "ready" | "error";
|
|
39
|
+
consent: AnalyticsConsent;
|
|
40
|
+
queueLength: number;
|
|
41
|
+
pageViewId: string | null;
|
|
42
|
+
error?: string;
|
|
43
|
+
lastDeliveredAt?: string;
|
|
44
|
+
}>;
|
|
45
|
+
subscribe(fn: () => void): () => void;
|
|
46
|
+
getAnonymousId: () => string | null;
|
|
47
|
+
getSessionId: () => string | null;
|
|
48
|
+
destroy(): void;
|
|
49
|
+
};
|
|
50
|
+
export type ViewOptions = {
|
|
51
|
+
viewKey?: string;
|
|
52
|
+
active?: boolean;
|
|
53
|
+
};
|
|
54
|
+
export type CheckoutOptions = {
|
|
55
|
+
checkoutKey?: string;
|
|
56
|
+
active?: boolean;
|
|
57
|
+
};
|
|
58
|
+
/** Uses the SDK's SPA page identity unless the application supplies a visit key. */
|
|
59
|
+
export declare function useProductView(properties: StandardEventInputMap['product_view'] | null | undefined, { viewKey, active }?: ViewOptions): void;
|
|
60
|
+
export type CheckoutProperties = Omit<StandardEventInputMap['begin_checkout'], 'checkoutId'> & {
|
|
61
|
+
checkoutId?: string;
|
|
62
|
+
};
|
|
63
|
+
/** A component/page visit owns the default attempt; explicit keys support custom checkout flows. */
|
|
64
|
+
export declare function useBeginCheckout(properties: CheckoutProperties | null | undefined, { checkoutKey, active }?: CheckoutOptions): void;
|
|
65
|
+
export type ConsentBannerProps = {
|
|
66
|
+
privacyPolicyUrl?: string;
|
|
67
|
+
labels?: Partial<{
|
|
68
|
+
message: string;
|
|
69
|
+
accept: string;
|
|
70
|
+
reject: string;
|
|
71
|
+
settings: string;
|
|
72
|
+
privacyPolicy: string;
|
|
73
|
+
}>;
|
|
74
|
+
className?: string;
|
|
75
|
+
style?: CSSProperties;
|
|
76
|
+
};
|
|
77
|
+
/** Optional UI. Omit it when connecting an existing banner; no second banner is installed automatically. */
|
|
78
|
+
export declare function SenderMasterConsentBanner({ privacyPolicyUrl, labels, className, style }: ConsentBannerProps): import("react").JSX.Element | null;
|
package/package.json
CHANGED
|
@@ -1,6 +1,39 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sendermaster/react",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "SenderMaster React integration with an embedded browser SDK",
|
|
5
|
+
"license": "UNLICENSED",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./dist/index.cjs",
|
|
8
|
+
"module": "./dist/index.js",
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"import": "./dist/index.js",
|
|
14
|
+
"require": "./dist/index.cjs"
|
|
15
|
+
},
|
|
16
|
+
"./browser": {
|
|
17
|
+
"types": "./dist/browser.d.ts",
|
|
18
|
+
"import": "./dist/browser.js",
|
|
19
|
+
"require": "./dist/browser.cjs"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"dist",
|
|
24
|
+
"README.md",
|
|
25
|
+
"CHANGELOG.md"
|
|
26
|
+
],
|
|
27
|
+
"sideEffects": false,
|
|
28
|
+
"peerDependencies": {
|
|
29
|
+
"react": "^18.2.0"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@types/react": "^18.3.0",
|
|
33
|
+
"react": "^18.2.0"
|
|
34
|
+
},
|
|
35
|
+
"publishConfig": {
|
|
36
|
+
"access": "public",
|
|
37
|
+
"registry": "https://registry.npmjs.org/"
|
|
38
|
+
}
|
|
39
|
+
}
|