@sendermaster/react 0.0.0-stage → 0.1.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 +3 -0
- package/README.md +33 -2
- package/dist/browser.cjs +2 -0
- package/dist/browser.d.ts +1 -0
- package/dist/browser.js +2 -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/core.d.ts +53 -0
- package/dist/types/browser/src/index.d.ts +40 -0
- package/dist/types/event-contracts/src/index.d.ts +250 -0
- package/dist/types/react/src/browser.d.ts +2 -0
- package/dist/types/react/src/index.d.ts +54 -0
- package/package.json +10 -5
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
# 0.1.0
|
|
2
|
+
|
|
3
|
+
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,34 @@
|
|
|
1
|
-
#
|
|
1
|
+
# SenderMaster React integration (0.1.0)
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Install `npm install ./sendermaster-react-0.1.0.tgz`. React 18.2+ within React 18 is the tested peer. The browser core is included; no separate browser package installation is required.
|
|
4
|
+
|
|
5
|
+
```tsx
|
|
6
|
+
'use client';
|
|
7
|
+
import { SenderMasterProvider, useProductView, useSenderMaster } from '@sendermaster/react';
|
|
8
|
+
function Product({ product, visitKey }) {
|
|
9
|
+
useProductView({ productId: String(product.id) }, { viewKey: visitKey });
|
|
10
|
+
const { track, status } = useSenderMaster();
|
|
11
|
+
return <button onClick={async () => {
|
|
12
|
+
const allowed = status.consent === 'granted';
|
|
13
|
+
await addCart(product.id);
|
|
14
|
+
if (allowed) track('add_to_cart', {productId:String(product.id), quantity:1});
|
|
15
|
+
}}>Add to cart</button>;
|
|
16
|
+
}
|
|
17
|
+
// Your existing cookie UI owns analyticsConsent: unknown | granted | denied.
|
|
18
|
+
<SenderMasterProvider siteKey="YOUR_PUBLIC_SITE_KEY" analyticsConsent={analyticsConsent}>
|
|
19
|
+
<Product product={product} visitKey={currentVisitKey} />
|
|
20
|
+
</SenderMasterProvider>
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Provider props: enabled/siteKey/apiHost/pageRules, analyticsConsent, marketingConsent (default false), consentSource, policyVersion, children. The wrapper is framework independent and safe during SSR. Do not mount providers with conflicting configurations in the same document. Repeated effects/Strict Mode reuse a client; final unmount destroys it.
|
|
24
|
+
|
|
25
|
+
`useProductView(properties|null,{viewKey,active?})` deduplicates by page visit and product/variant. Pass a changing visit key for your router. `active:false` represents a closed quick view. `useBeginCheckout(properties|null,{checkoutKey,active?})` reports one valid snapshot per checkout key; pricing recalculations do not retrigger. Pass null while business data is unavailable. Leaving and returning creates a new hook instance and may report again. Actions before consent are not replayed; the currently displayed product/checkout may be reported upon consent.
|
|
26
|
+
|
|
27
|
+
For non-component business code:
|
|
28
|
+
```js
|
|
29
|
+
import { senderMaster } from '@sendermaster/react/browser';
|
|
30
|
+
// Shared with the Provider, without importing React into this module.
|
|
31
|
+
senderMaster.track('search', {query:'thermal scope'});
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Business IDs, prices, currencies and success conditions remain your responsibility. Use the public Site Key only. See the browser README for queue, consent, status and compatibility behavior.
|
package/dist/browser.cjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use strict";var te=Object.defineProperty;var Re=Object.getOwnPropertyDescriptor;var Oe=Object.getOwnPropertyNames;var De=Object.prototype.hasOwnProperty;var Le=(r,o)=>{for(var a in o)te(r,a,{get:o[a],enumerable:!0})},je=(r,o,a,n)=>{if(o&&typeof o=="object"||typeof o=="function")for(let i of Oe(o))!De.call(r,i)&&i!==a&&te(r,i,{get:()=>o[i],enumerable:!(n=Re(o,i))||n.enumerable});return r};var Ke=r=>je(te({},"__esModule",{value:!0}),r);var et={};Le(et,{senderMaster:()=>Te});module.exports=Ke(et);var He={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"}]},Ue=[{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"}],A=256,We=500,he=100,Ie=50,be=3,ve=16*1024,Je=/(password|passcode|secret|token|api.?key|card.?number|cvv|cvc|security.?code|ssn|passport)/i,Fe=Object.fromEntries(Object.entries(He).map(([r,o])=>[r,o.map(a=>a.name)]));function ze(r,o){let a=[];if(!j(o))return[{path:"properties",message:"must be an object"}];let n=o;for(let i of Object.keys(n))Fe[r].includes(i)||a.push({path:`properties.${i}`,message:"is not a supported standard field; place extension data under custom"});return r==="wishlist_added"?(b(n,"productId",a,!n.catalogProductId,A),b(n,"listName",a,!1,A)):r==="product_view"||r==="add_to_cart"?(b(n,"productId",a,!n.catalogProductId,A),b(n,"variantId",a,!1,A),ae(n,"amount",a,!1,!1),Se(n,a,!1),n.amount===void 0!=(n.currency===void 0)&&a.push({path:"properties.amount",message:"amount and currency must be provided together"}),r==="add_to_cart"&&se(n,"quantity",a,!0,1)):r==="begin_checkout"?(b(n,"checkoutId",a,!0,A),ae(n,"amount",a,!0,!1),Se(n,a,!0),!Array.isArray(n.items)||n.items.length<1||n.items.length>he?a.push({path:"properties.items",message:`must contain 1-${he} items`}):n.items.forEach((i,c)=>Be(i,c,a))):(b(n,"query",a,!0,We),se(n,"resultsCount",a,!1,0)),["product_view","add_to_cart","wishlist_added"].includes(r)&&(b(n,"catalogProductId",a,!1,100),b(n,"catalogVariantId",a,!1,100),n.catalogVariantId&&!n.catalogProductId&&a.push({path:"properties.catalogVariantId",message:"requires catalogProductId"})),n.custom!==void 0&&Qe(n.custom,a),a}function we(r,o){let a=ze(r,o);if(a.length)throw new ne(r,a);let n=o,i={};for(let c of["variantId","quantity","checkoutId","items","query","resultsCount","listName","custom"])n[c]!==void 0&&(i[c]=n[c]);return{...typeof n.productId=="string"?{productId:n.productId}:{},...typeof n.catalogProductId=="string"?{catalogProductId:n.catalogProductId}:{},...typeof n.catalogVariantId=="string"?{catalogVariantId:n.catalogVariantId}:{},...typeof n.amount=="number"?{amount:n.amount}:{},...typeof n.currency=="string"?{currency:n.currency}:{},properties:i}}var ne=class extends Error{constructor(a,n){super(`Invalid ${a} event: ${n.map(i=>`${i.path} ${i.message}`).join("; ")}`);this.eventName=a;this.issues=n;this.name="StandardEventValidationError"}eventName;issues};function Be(r,o,a){let n=`properties.items[${o}]`;if(!j(r)){a.push({path:n,message:"must be an object"});return}let i=r,c=Ue.map(u=>u.name);for(let u of Object.keys(i))c.includes(u)||a.push({path:`${n}.${u}`,message:"is not supported"});b(i,"productId",a,!i.catalogProductId,A,n),b(i,"catalogProductId",a,!1,100,n),b(i,"catalogVariantId",a,!1,100,n),i.catalogVariantId&&!i.catalogProductId&&a.push({path:`${n}.catalogVariantId`,message:"requires catalogProductId"}),b(i,"variantId",a,!1,A,n),se(i,"quantity",a,!0,1,n),ae(i,"amount",a,!1,!1,n)}function Qe(r,o){if(!j(r)){o.push({path:"properties.custom",message:"must be an object"});return}let a=r;Object.keys(a).length>Ie&&o.push({path:"properties.custom",message:`must contain at most ${Ie} top-level fields`}),re(a,"properties.custom",1,o,new WeakSet);try{new TextEncoder().encode(JSON.stringify(a)).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(r,o,a,n,i){if(a>be){n.push({path:o,message:`must not exceed ${be} levels`});return}if(!(r===null||typeof r=="string"||typeof r=="boolean"||typeof r=="number"&&Number.isFinite(r))){if(typeof r=="object"&&r){if(i.has(r)){n.push({path:o,message:"must not contain circular references"});return}i.add(r)}if(Array.isArray(r)){r.forEach((c,u)=>re(c,`${o}[${u}]`,a+1,n,i));return}if(j(r)){Object.entries(r).forEach(([c,u])=>{(c.startsWith("_")||c.toLowerCase().startsWith("sm_"))&&n.push({path:`${o}.${c}`,message:"uses a reserved prefix"}),Je.test(c)&&n.push({path:`${o}.${c}`,message:"must not contain secrets or sensitive payment/identity data"}),re(u,`${o}.${c}`,a+1,n,i)});return}n.push({path:o,message:"must contain JSON-compatible values only"})}}function j(r){if(!r||typeof r!="object"||Array.isArray(r))return!1;let o=Object.getPrototypeOf(r);return o===Object.prototype||o===null}function b(r,o,a,n,i,c="properties"){let u=r[o];if(u===void 0){n&&a.push({path:`${c}.${o}`,message:"is required"});return}(typeof u!="string"||u.length<1||u.length>i)&&a.push({path:`${c}.${o}`,message:`must be a string with 1-${i} characters`})}function ae(r,o,a,n,i,c="properties"){let u=r[o];if(u===void 0){n&&a.push({path:`${c}.${o}`,message:"is required"});return}(typeof u!="number"||!Number.isFinite(u)||(i?u<=0:u<0))&&a.push({path:`${c}.${o}`,message:i?"must be a positive finite number":"must be a non-negative finite number"})}function se(r,o,a,n,i,c="properties"){let u=r[o];if(u===void 0){n&&a.push({path:`${c}.${o}`,message:"is required"});return}(typeof u!="number"||!Number.isInteger(u)||u<i)&&a.push({path:`${c}.${o}`,message:`must be an integer greater than or equal to ${i}`})}function Se(r,o,a){let n=r.currency;if(n===void 0){a&&o.push({path:"properties.currency",message:"is required"});return}(typeof n!="string"||!/^[A-Z]{3}$/.test(n))&&o.push({path:"properties.currency",message:"must be a 3-letter uppercase currency code"})}var Ee=1800*1e3,Xe=1440*60*1e3,Ye=/\.(?:pdf|csv|docx?|xlsx?|pptx?|zip|rar|7z)(?:$|[?#])/i,K=Object.freeze({state:"disabled",consent:"unknown",queueLength:0,pageViewId:null});function _e(r,o=!1){let a=o?"robot_store":`sendermaster:${r.siteKey}`,n={anonymous:`${a}_anonymous_id`,session:`${a}_session`,consent:`${a}_consent`,queue:`${a}_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 u(e,t){i.set(e,t);try{localStorage.setItem(e,t)}catch{}}function H(e){i.delete(e);try{localStorage.removeItem(e)}catch{}}function x(e){try{return JSON.parse(c(e)??"null")}catch{return null}}let V=new Set,T={analytics:"unknown"},q={...K,state:r.enabled===!1||!r.siteKey?"disabled":"waiting_consent"},p=!1,v=0,$,R=!1,O,M=0,P=0,l,U=!1,W=location.href,J=new WeakSet,k=new WeakMap,g=[],F=[];function w(e={}){let t={...q,consent:T.analytics,queueLength:g.length,pageViewId:l?.id??null,...e};if(JSON.stringify(t)!==JSON.stringify(q)){q=Object.freeze(t);for(let s of V)try{s()}catch{}}}function S(e,t,s,d){let f=v,I=E=>{if(p&&v===f)try{s(E)}catch{}};e.addEventListener(t,I,d),F.push(()=>e.removeEventListener(t,I,d))}function oe(){return(r.apiHost??"https://api.sendermaster.com").replace(/\/$/,"")}function z(){let e=c(n.anonymous);return e||(e=crypto.randomUUID(),u(n.anonymous,e)),e}function B(){let e=x(n.session);return e&&typeof e.id=="string"&&typeof e.lastActivityAt=="number"?e:void 0}function Q(){let e=Date.now(),t=B();if(!t||e-t.lastActivityAt>=Ee){let s={id:crypto.randomUUID(),lastActivityAt:e};return u(n.session,JSON.stringify(s)),s.id}return t.lastActivityAt=e,u(n.session,JSON.stringify(t)),t.id}function X(){let e=Date.now();g=g.filter(t=>t.siteKey===r.siteKey&&e-Date.parse(t.event.occurredAt)<Xe&&Date.parse(t.event.occurredAt)<=e+6e4).slice(-100)}function D(){X(),u(n.queue,JSON.stringify(g)),w()}function qe(){let e=x(n.queue);Array.isArray(e)&&(g=e.flatMap(t=>{if(t?.event?.eventId&&typeof t.anonymousId=="string"&&typeof t.sessionId=="string")return[t];let s=c(n.anonymous),d=B();return o&&t?.eventId&&s&&d?[{siteKey:r.siteKey,anonymousId:s,sessionId:d.id,event:t}]:[]}),X())}function ie(e){let t=new URL(e);return["email","token","password","access_token"].forEach(s=>t.searchParams.delete(s)),t.toString()}function ce(e){try{return new URL(e).origin}catch{return}}function Ae(){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 r.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={},s={}){if(!p)return;let{productId:d,catalogProductId:f,catalogVariantId:I,amount:E,currency:m,pageType:C,...N}=t,h={eventId:crypto.randomUUID(),name:e,occurredAt:new Date().toISOString(),url:s.url??ie(location.href),path:s.path??location.pathname,...ce(document.referrer)?{referrer:ce(document.referrer)}:{},...typeof d=="string"?{productId:d}:{},...typeof f=="string"?{catalogProductId:f}:{},...typeof I=="string"?{catalogVariantId:I}:{},...typeof E=="number"?{amount:E}:{},...typeof m=="string"?{currency:m}:{},pageType:s.pageType??(typeof C=="string"?C:l?.pageType),pageViewId:s.pageViewId??l?.id,...s.engagedTimeMsec?{engagedTimeMsec:s.engagedTimeMsec}:{},...Object.keys(N).length?{properties:N}:{},context:Ae()};return g.push({siteKey:r.siteKey,anonymousId:z(),sessionId:Q(),event:JSON.parse(JSON.stringify(h))}),D(),g.length>=20&&L(),h.eventId}function Pe(e,t){if(q.state==="disabled")return{queued:!1,reason:"disabled"};if(T.analytics!=="granted")return{queued:!1,reason:"consent_required"};if(!p)return{queued:!1,reason:"unavailable"};try{let s=we(e,t),d=y(e,{...s.properties,productId:s.productId,catalogProductId:s.catalogProductId,catalogVariantId:s.catalogVariantId,amount:s.amount,currency:s.currency});return d?{queued:!0,eventId:d}:{queued:!1,reason:"unavailable"}}catch(s){return{queued:!1,reason:"invalid_event",message:s instanceof Error?s.message:"Invalid event"}}}async function L(e=!1){if(!p||R||(X(),w(),!g.length||!e&&Date.now()<M))return;let t=g[0],s=g.filter(m=>m.siteKey===t.siteKey&&m.anonymousId===t.anonymousId&&m.sessionId===t.sessionId).slice(0,20),d=JSON.stringify({siteKey:t.siteKey,anonymousId:t.anonymousId,sessionId:t.sessionId,events:s.map(m=>m.event)}),f=`${oe()}/v2/collect/events`;if(e)try{if(navigator.sendBeacon?.(f,new Blob([d],{type:"application/json"}))){D();return}}catch{}R=!0;let I=v,E=new AbortController;O=E;try{let m=await fetch(f,{method:"POST",headers:{"content-type":"application/json"},body:d,keepalive:!0,signal:E.signal});if(I!==v||!p)return;if(!m.ok){if(m.status===429||m.status>=500)throw new Error(`Collect HTTP ${m.status}`);let h=new Set(s.map(ee=>ee.event.eventId));g=g.filter(ee=>!h.has(ee.event.eventId)),D(),w({state:"error",error:`Collect HTTP ${m.status}: batch discarded`}),M=0,P=0;return}let C=await m.json();if(!Array.isArray(C.results))throw new Error("Collect response missing results");let N=new Set(C.results.filter(h=>h.status==="accepted"||h.status==="duplicate").map(h=>h.eventId));if(!s.every(h=>N.has(h.event.eventId)))throw new Error("Collect response incomplete");if(I!==v||!p)return;g=g.filter(h=>!N.has(h.event.eventId)),P=0,M=0,D(),w({state:"ready",error:void 0,lastDeliveredAt:new Date().toISOString()})}catch(m){if(I!==v||!p)return;P++,M=Date.now()+Math.min(6e4,3e3*2**Math.min(P-1,5)),w({error:m instanceof Error?m.message:"Collect unavailable"})}finally{I===v&&(R=!1,O=void 0)}p&&g.length&&!M&&L()}function ue(e,t){let s=JSON.stringify({siteKey:r.siteKey,anonymousId:t,analyticsAllowed:e.analytics==="granted",marketingAllowed:e.marketing??!1,source:e.source??"sdk",policyVersion:e.policyVersion});try{fetch(`${oe()}/v2/collect/consent`,{method:"POST",headers:{"content-type":"application/json"},body:s,keepalive:!0}).then(d=>{if(!d.ok)throw new Error(`Consent HTTP ${d.status}`)}).catch(()=>{})}catch{}}function le(){l={id:crypto.randomUUID(),url:ie(location.href),path:location.pathname,pageType:Me(),enteredAt:new Date().toISOString(),visibleAt:document.visibilityState==="visible"?Date.now():0,activeMsec:0,reportedMsec:0,maxScrollPercent:de()},U=!1,y("page_view")}function ke(){!p||!l?.visibleAt||(l.activeMsec+=Date.now()-l.visibleAt,l.visibleAt=0)}function Y(e){if(!p||!l)return;ke();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 Ce(){p&&l&&!l.visibleAt&&(l.visibleAt=Date.now())}function pe(){!p||location.href===W||(Y("navigation"),W=location.href,le())}function Ne(){let e=v,t=s=>{let d=history[s];history[s]=function(...I){let E=d.apply(this,I);return queueMicrotask(()=>{p&&v===e&&pe()}),E};let f=history[s];F.push(()=>{history[s]===f&&(history[s]=d)})};t("pushState"),t("replaceState"),S(window,"popstate",pe)}function xe(e){let t=$e(e),s=Array.from(document.querySelectorAll("video")).indexOf(e);return{videoId:e.dataset.robotVideoId||e.id||t||`video:${location.pathname}:${s}`,videoTitle:e.dataset.robotVideoTitle||e.getAttribute("title")||void 0,productId:e.dataset.robotProductId||void 0,videoSrc:t}}function G(e,t,s){return{...xe(e),watchedSeconds:Math.round(t.watchedSeconds*10)/10,durationSeconds:Math.round(e.duration*10)/10,...s!==void 0?{progressPercent:s}:{}}}function me(e,t){let s=Date.now(),d=e.currentTime-t.lastMediaTime,f=(s-t.lastWallTime)/1e3;d>0&&f>0&&d<=Math.max(3,f+1)&&(t.watchedSeconds+=Math.min(d,f+.5)),t.lastMediaTime=e.currentTime,t.lastWallTime=s}function ge(e,t){if(!e.duration)return;let s=Math.min(100,Math.floor(e.currentTime/e.duration*100));for(let d of[25,50,75,100])s>=d&&!t.milestones.has(d)&&(t.milestones.add(d),y("video_progress",G(e,t,d)))}function Ve(){S(window,"scroll",()=>{l&&(l.maxScrollPercent=Math.max(l.maxScrollPercent,de()),!U&&l.maxScrollPercent>=90&&(U=!0,y("scroll",{percent:90})))},{passive:!0}),S(document,"focusin",e=>{let t=e.target?.closest("form");t&&!J.has(t)&&(J.add(t),y("form_start",{formId:t.id||void 0,formName:t.getAttribute("name")||void 0}))}),S(document,"submit",e=>{let t=e.target;t instanceof HTMLFormElement&&y("form_submitted",{formId:t.id||void 0,formName:t.getAttribute("name")||void 0})}),S(document,"click",e=>{let t=e.target?.closest("a[href]");if(!t)return;let s=t.href,d=t.origin!==location.origin;t.hasAttribute("download")||Ye.test(s)?y("file_download",{fileName:t.pathname.split("/").pop(),linkDomain:t.hostname||void 0}):(d||/^mailto:|^tel:/i.test(t.getAttribute("href")??""))&&y("click",{linkDomain:t.hostname||void 0,linkType:s.startsWith("mailto:")?"email":s.startsWith("tel:")?"phone":"outbound"})}),S(document,"play",e=>{let t=e.target;if(!(t instanceof HTMLVideoElement))return;let s=k.get(t);s||(s={milestones:new Set,watchedSeconds:0,lastMediaTime:t.currentTime,lastWallTime:Date.now(),started:!1},k.set(t,s)),s.started||(s.started=!0,y("video_start",G(t,s))),s.lastMediaTime=t.currentTime,s.lastWallTime=Date.now()},!0),S(document,"timeupdate",e=>{let t=e.target;if(!(t instanceof HTMLVideoElement))return;let s=k.get(t);s&&(me(t,s),ge(t,s))},!0),S(document,"ended",e=>{let t=e.target;if(!(t instanceof HTMLVideoElement))return;let s=k.get(t);s&&(me(t,s),ge(t,s),y("video_complete",G(t,s,100)))},!0),S(document,"visibilitychange",()=>{document.visibilityState==="hidden"?Y("hidden"):Ce()})}function $e(e){try{return e.currentSrc?new URL(e.currentSrc).origin+new URL(e.currentSrc).pathname:void 0}catch{return}}function fe(){if(!(p||q.state==="disabled"||T.analytics!=="granted"))try{let e=!c(n.anonymous),t=B();qe(),z(),Q(),p=!0,v++,W=location.href,J=new WeakSet,k=new WeakMap,le(),e&&y("first_visit"),(!t||Date.now()-t.lastActivityAt>=Ee)&&y("session_start"),Ve(),Ne(),S(window,"pagehide",()=>{Y("pagehide"),L(!0)}),$=window.setInterval(()=>{L()},3e3),w({state:"ready",error:void 0}),window.dispatchEvent(new Event("robot:ready"))}catch(e){Z(!1),w({state:"error",error:e instanceof Error?e.message:"Initialization failed"})}}function Z(e){p=!1,v++,O?.abort(),O=void 0,R=!1,$!==void 0&&window.clearInterval($),$=void 0;for(let t of F.splice(0).reverse())t();l=void 0,M=0,P=0,e&&(g=[],H(n.queue),H(n.anonymous),H(n.session))}function ye(e){if(q.state==="disabled")return;let t=JSON.stringify(T)!==JSON.stringify(e),s=p?c(n.anonymous):null;T={...e},o&&u(n.consent,JSON.stringify({...e,analytics:e.analytics==="granted"})),e.analytics!=="granted"?(Z(e.analytics==="denied"||!!s),w({state:"waiting_consent",error:void 0}),t&&s&&ue(e,s)):(fe(),t&&p&&ue(e,z()))}return{track:Pe,setConsent:ye,start:fe,restoreLegacyConsent:()=>{o&&T.analytics==="unknown"&&x(n.consent)?.analytics===!0&&ye({...x(n.consent),analytics:"granted"})},getStatus:()=>q,subscribe:e=>(V.add(e),()=>{V.delete(e)}),getAnonymousId:()=>p?c(n.anonymous):null,getSessionId:()=>p?Q():null,destroy:()=>{Z(!1),T={analytics:"unknown"},w({state:"disabled"}),V.clear()}}}var Ge=Symbol.for("sendermaster.browser.v1");function _(){if(typeof window>"u")return;let r=window;return r[Ge]||={subscribers:new Set}}function Ze(r,o){let a=_();if(!a)return K;let n={...r,siteKey:r.siteKey?.trim()||"",apiHost:(r.apiHost||"https://api.sendermaster.com").replace(/\/$/,""),enabled:r.enabled!==!1},i=JSON.stringify(n);if(a.client&&a.fingerprint===i)return a.client.getStatus();a.client?.destroy(),a.fingerprint=i,a.client=_e(n,o),a.client.subscribe(()=>{for(let c of a.subscribers)try{c()}catch{}});for(let c of a.subscribers)try{c()}catch{}return a.client.getStatus()}var Te={init:r=>Ze(r,!1),setConsent:r=>_()?.client?.setConsent(r),track(r,o){return _()?.client?.track(r,o)??{queued:!1,reason:"disabled"}},getStatus:()=>_()?.client?.getStatus()??K,subscribe(r){let o=_();return o?(o.subscribers.add(r),()=>{o.subscribers.delete(r)}):()=>{}},getAnonymousId:()=>_()?.client?.getAnonymousId()??null,getSessionId:()=>_()?.client?.getSessionId()??null,destroy(){let r=_();if(r){r.client?.destroy(),r.client=void 0,r.fingerprint=void 0;for(let o of r.subscribers)try{o()}catch{}}}};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './types/react/src/browser';
|
package/dist/browser.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
var Ve={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"}]},$e=[{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"}],A=256,Re=500,ye=100,he=50,Ie=3,be=16*1024,Oe=/(password|passcode|secret|token|api.?key|card.?number|cvv|cvc|security.?code|ssn|passport)/i,De=Object.fromEntries(Object.entries(Ve).map(([r,o])=>[r,o.map(s=>s.name)]));function Le(r,o){let s=[];if(!j(o))return[{path:"properties",message:"must be an object"}];let n=o;for(let i of Object.keys(n))De[r].includes(i)||s.push({path:`properties.${i}`,message:"is not a supported standard field; place extension data under custom"});return r==="wishlist_added"?(b(n,"productId",s,!n.catalogProductId,A),b(n,"listName",s,!1,A)):r==="product_view"||r==="add_to_cart"?(b(n,"productId",s,!n.catalogProductId,A),b(n,"variantId",s,!1,A),re(n,"amount",s,!1,!1),ve(n,s,!1),n.amount===void 0!=(n.currency===void 0)&&s.push({path:"properties.amount",message:"amount and currency must be provided together"}),r==="add_to_cart"&&ae(n,"quantity",s,!0,1)):r==="begin_checkout"?(b(n,"checkoutId",s,!0,A),re(n,"amount",s,!0,!1),ve(n,s,!0),!Array.isArray(n.items)||n.items.length<1||n.items.length>ye?s.push({path:"properties.items",message:`must contain 1-${ye} items`}):n.items.forEach((i,c)=>je(i,c,s))):(b(n,"query",s,!0,Re),ae(n,"resultsCount",s,!1,0)),["product_view","add_to_cart","wishlist_added"].includes(r)&&(b(n,"catalogProductId",s,!1,100),b(n,"catalogVariantId",s,!1,100),n.catalogVariantId&&!n.catalogProductId&&s.push({path:"properties.catalogVariantId",message:"requires catalogProductId"})),n.custom!==void 0&&Ke(n.custom,s),s}function Se(r,o){let s=Le(r,o);if(s.length)throw new te(r,s);let n=o,i={};for(let c of["variantId","quantity","checkoutId","items","query","resultsCount","listName","custom"])n[c]!==void 0&&(i[c]=n[c]);return{...typeof n.productId=="string"?{productId:n.productId}:{},...typeof n.catalogProductId=="string"?{catalogProductId:n.catalogProductId}:{},...typeof n.catalogVariantId=="string"?{catalogVariantId:n.catalogVariantId}:{},...typeof n.amount=="number"?{amount:n.amount}:{},...typeof n.currency=="string"?{currency:n.currency}:{},properties:i}}var te=class extends Error{constructor(s,n){super(`Invalid ${s} event: ${n.map(i=>`${i.path} ${i.message}`).join("; ")}`);this.eventName=s;this.issues=n;this.name="StandardEventValidationError"}eventName;issues};function je(r,o,s){let n=`properties.items[${o}]`;if(!j(r)){s.push({path:n,message:"must be an object"});return}let i=r,c=$e.map(u=>u.name);for(let u of Object.keys(i))c.includes(u)||s.push({path:`${n}.${u}`,message:"is not supported"});b(i,"productId",s,!i.catalogProductId,A,n),b(i,"catalogProductId",s,!1,100,n),b(i,"catalogVariantId",s,!1,100,n),i.catalogVariantId&&!i.catalogProductId&&s.push({path:`${n}.catalogVariantId`,message:"requires catalogProductId"}),b(i,"variantId",s,!1,A,n),ae(i,"quantity",s,!0,1,n),re(i,"amount",s,!1,!1,n)}function Ke(r,o){if(!j(r)){o.push({path:"properties.custom",message:"must be an object"});return}let s=r;Object.keys(s).length>he&&o.push({path:"properties.custom",message:`must contain at most ${he} top-level fields`}),ne(s,"properties.custom",1,o,new WeakSet);try{new TextEncoder().encode(JSON.stringify(s)).length>be&&o.push({path:"properties.custom",message:`must be at most ${be} bytes`})}catch{o.push({path:"properties.custom",message:"must be valid JSON data"})}}function ne(r,o,s,n,i){if(s>Ie){n.push({path:o,message:`must not exceed ${Ie} levels`});return}if(!(r===null||typeof r=="string"||typeof r=="boolean"||typeof r=="number"&&Number.isFinite(r))){if(typeof r=="object"&&r){if(i.has(r)){n.push({path:o,message:"must not contain circular references"});return}i.add(r)}if(Array.isArray(r)){r.forEach((c,u)=>ne(c,`${o}[${u}]`,s+1,n,i));return}if(j(r)){Object.entries(r).forEach(([c,u])=>{(c.startsWith("_")||c.toLowerCase().startsWith("sm_"))&&n.push({path:`${o}.${c}`,message:"uses a reserved prefix"}),Oe.test(c)&&n.push({path:`${o}.${c}`,message:"must not contain secrets or sensitive payment/identity data"}),ne(u,`${o}.${c}`,s+1,n,i)});return}n.push({path:o,message:"must contain JSON-compatible values only"})}}function j(r){if(!r||typeof r!="object"||Array.isArray(r))return!1;let o=Object.getPrototypeOf(r);return o===Object.prototype||o===null}function b(r,o,s,n,i,c="properties"){let u=r[o];if(u===void 0){n&&s.push({path:`${c}.${o}`,message:"is required"});return}(typeof u!="string"||u.length<1||u.length>i)&&s.push({path:`${c}.${o}`,message:`must be a string with 1-${i} characters`})}function re(r,o,s,n,i,c="properties"){let u=r[o];if(u===void 0){n&&s.push({path:`${c}.${o}`,message:"is required"});return}(typeof u!="number"||!Number.isFinite(u)||(i?u<=0:u<0))&&s.push({path:`${c}.${o}`,message:i?"must be a positive finite number":"must be a non-negative finite number"})}function ae(r,o,s,n,i,c="properties"){let u=r[o];if(u===void 0){n&&s.push({path:`${c}.${o}`,message:"is required"});return}(typeof u!="number"||!Number.isInteger(u)||u<i)&&s.push({path:`${c}.${o}`,message:`must be an integer greater than or equal to ${i}`})}function ve(r,o,s){let n=r.currency;if(n===void 0){s&&o.push({path:"properties.currency",message:"is required"});return}(typeof n!="string"||!/^[A-Z]{3}$/.test(n))&&o.push({path:"properties.currency",message:"must be a 3-letter uppercase currency code"})}var we=1800*1e3,He=1440*60*1e3,Ue=/\.(?:pdf|csv|docx?|xlsx?|pptx?|zip|rar|7z)(?:$|[?#])/i,K=Object.freeze({state:"disabled",consent:"unknown",queueLength:0,pageViewId:null});function Ee(r,o=!1){let s=o?"robot_store":`sendermaster:${r.siteKey}`,n={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 u(e,t){i.set(e,t);try{localStorage.setItem(e,t)}catch{}}function H(e){i.delete(e);try{localStorage.removeItem(e)}catch{}}function x(e){try{return JSON.parse(c(e)??"null")}catch{return null}}let V=new Set,T={analytics:"unknown"},q={...K,state:r.enabled===!1||!r.siteKey?"disabled":"waiting_consent"},p=!1,v=0,$,R=!1,O,M=0,P=0,l,U=!1,W=location.href,J=new WeakSet,k=new WeakMap,g=[],F=[];function w(e={}){let t={...q,consent:T.analytics,queueLength:g.length,pageViewId:l?.id??null,...e};if(JSON.stringify(t)!==JSON.stringify(q)){q=Object.freeze(t);for(let a of V)try{a()}catch{}}}function S(e,t,a,d){let f=v,I=E=>{if(p&&v===f)try{a(E)}catch{}};e.addEventListener(t,I,d),F.push(()=>e.removeEventListener(t,I,d))}function se(){return(r.apiHost??"https://api.sendermaster.com").replace(/\/$/,"")}function z(){let e=c(n.anonymous);return e||(e=crypto.randomUUID(),u(n.anonymous,e)),e}function B(){let e=x(n.session);return e&&typeof e.id=="string"&&typeof e.lastActivityAt=="number"?e:void 0}function Q(){let e=Date.now(),t=B();if(!t||e-t.lastActivityAt>=we){let a={id:crypto.randomUUID(),lastActivityAt:e};return u(n.session,JSON.stringify(a)),a.id}return t.lastActivityAt=e,u(n.session,JSON.stringify(t)),t.id}function X(){let e=Date.now();g=g.filter(t=>t.siteKey===r.siteKey&&e-Date.parse(t.event.occurredAt)<He&&Date.parse(t.event.occurredAt)<=e+6e4).slice(-100)}function D(){X(),u(n.queue,JSON.stringify(g)),w()}function _e(){let e=x(n.queue);Array.isArray(e)&&(g=e.flatMap(t=>{if(t?.event?.eventId&&typeof t.anonymousId=="string"&&typeof t.sessionId=="string")return[t];let a=c(n.anonymous),d=B();return o&&t?.eventId&&a&&d?[{siteKey:r.siteKey,anonymousId:a,sessionId:d.id,event:t}]:[]}),X())}function oe(e){let t=new URL(e);return["email","token","password","access_token"].forEach(a=>t.searchParams.delete(a)),t.toString()}function ie(e){try{return new URL(e).origin}catch{return}}function Te(){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 r.pageRules?.find(t=>e.startsWith(t.pathPrefix))?.pageType}function ce(){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:d,catalogProductId:f,catalogVariantId:I,amount:E,currency:m,pageType:C,...N}=t,h={eventId:crypto.randomUUID(),name:e,occurredAt:new Date().toISOString(),url:a.url??oe(location.href),path:a.path??location.pathname,...ie(document.referrer)?{referrer:ie(document.referrer)}:{},...typeof d=="string"?{productId:d}:{},...typeof f=="string"?{catalogProductId:f}:{},...typeof I=="string"?{catalogVariantId:I}:{},...typeof E=="number"?{amount:E}:{},...typeof m=="string"?{currency:m}:{},pageType:a.pageType??(typeof C=="string"?C:l?.pageType),pageViewId:a.pageViewId??l?.id,...a.engagedTimeMsec?{engagedTimeMsec:a.engagedTimeMsec}:{},...Object.keys(N).length?{properties:N}:{},context:Te()};return g.push({siteKey:r.siteKey,anonymousId:z(),sessionId:Q(),event:JSON.parse(JSON.stringify(h))}),D(),g.length>=20&&L(),h.eventId}function Ae(e,t){if(q.state==="disabled")return{queued:!1,reason:"disabled"};if(T.analytics!=="granted")return{queued:!1,reason:"consent_required"};if(!p)return{queued:!1,reason:"unavailable"};try{let a=Se(e,t),d=y(e,{...a.properties,productId:a.productId,catalogProductId:a.catalogProductId,catalogVariantId:a.catalogVariantId,amount:a.amount,currency:a.currency});return d?{queued:!0,eventId:d}:{queued:!1,reason:"unavailable"}}catch(a){return{queued:!1,reason:"invalid_event",message:a instanceof Error?a.message:"Invalid event"}}}async function L(e=!1){if(!p||R||(X(),w(),!g.length||!e&&Date.now()<M))return;let t=g[0],a=g.filter(m=>m.siteKey===t.siteKey&&m.anonymousId===t.anonymousId&&m.sessionId===t.sessionId).slice(0,20),d=JSON.stringify({siteKey:t.siteKey,anonymousId:t.anonymousId,sessionId:t.sessionId,events:a.map(m=>m.event)}),f=`${se()}/v2/collect/events`;if(e)try{if(navigator.sendBeacon?.(f,new Blob([d],{type:"application/json"}))){D();return}}catch{}R=!0;let I=v,E=new AbortController;O=E;try{let m=await fetch(f,{method:"POST",headers:{"content-type":"application/json"},body:d,keepalive:!0,signal:E.signal});if(I!==v||!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(ee=>ee.event.eventId));g=g.filter(ee=>!h.has(ee.event.eventId)),D(),w({state:"error",error:`Collect HTTP ${m.status}: batch discarded`}),M=0,P=0;return}let C=await m.json();if(!Array.isArray(C.results))throw new Error("Collect response missing results");let N=new Set(C.results.filter(h=>h.status==="accepted"||h.status==="duplicate").map(h=>h.eventId));if(!a.every(h=>N.has(h.event.eventId)))throw new Error("Collect response incomplete");if(I!==v||!p)return;g=g.filter(h=>!N.has(h.event.eventId)),P=0,M=0,D(),w({state:"ready",error:void 0,lastDeliveredAt:new Date().toISOString()})}catch(m){if(I!==v||!p)return;P++,M=Date.now()+Math.min(6e4,3e3*2**Math.min(P-1,5)),w({error:m instanceof Error?m.message:"Collect unavailable"})}finally{I===v&&(R=!1,O=void 0)}p&&g.length&&!M&&L()}function de(e,t){let a=JSON.stringify({siteKey:r.siteKey,anonymousId:t,analyticsAllowed:e.analytics==="granted",marketingAllowed:e.marketing??!1,source:e.source??"sdk",policyVersion:e.policyVersion});try{fetch(`${se()}/v2/collect/consent`,{method:"POST",headers:{"content-type":"application/json"},body:a,keepalive:!0}).then(d=>{if(!d.ok)throw new Error(`Consent HTTP ${d.status}`)}).catch(()=>{})}catch{}}function ue(){l={id:crypto.randomUUID(),url:oe(location.href),path:location.pathname,pageType:qe(),enteredAt:new Date().toISOString(),visibleAt:document.visibilityState==="visible"?Date.now():0,activeMsec:0,reportedMsec:0,maxScrollPercent:ce()},U=!1,y("page_view")}function Me(){!p||!l?.visibleAt||(l.activeMsec+=Date.now()-l.visibleAt,l.visibleAt=0)}function Y(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 le(){!p||location.href===W||(Y("navigation"),W=location.href,ue())}function ke(){let e=v,t=a=>{let d=history[a];history[a]=function(...I){let E=d.apply(this,I);return queueMicrotask(()=>{p&&v===e&&le()}),E};let f=history[a];F.push(()=>{history[a]===f&&(history[a]=d)})};t("pushState"),t("replaceState"),S(window,"popstate",le)}function Ce(e){let t=xe(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 G(e,t,a){return{...Ce(e),watchedSeconds:Math.round(t.watchedSeconds*10)/10,durationSeconds:Math.round(e.duration*10)/10,...a!==void 0?{progressPercent:a}:{}}}function pe(e,t){let a=Date.now(),d=e.currentTime-t.lastMediaTime,f=(a-t.lastWallTime)/1e3;d>0&&f>0&&d<=Math.max(3,f+1)&&(t.watchedSeconds+=Math.min(d,f+.5)),t.lastMediaTime=e.currentTime,t.lastWallTime=a}function me(e,t){if(!e.duration)return;let a=Math.min(100,Math.floor(e.currentTime/e.duration*100));for(let d of[25,50,75,100])a>=d&&!t.milestones.has(d)&&(t.milestones.add(d),y("video_progress",G(e,t,d)))}function Ne(){S(window,"scroll",()=>{l&&(l.maxScrollPercent=Math.max(l.maxScrollPercent,ce()),!U&&l.maxScrollPercent>=90&&(U=!0,y("scroll",{percent:90})))},{passive:!0}),S(document,"focusin",e=>{let t=e.target?.closest("form");t&&!J.has(t)&&(J.add(t),y("form_start",{formId:t.id||void 0,formName:t.getAttribute("name")||void 0}))}),S(document,"submit",e=>{let t=e.target;t instanceof HTMLFormElement&&y("form_submitted",{formId:t.id||void 0,formName:t.getAttribute("name")||void 0})}),S(document,"click",e=>{let t=e.target?.closest("a[href]");if(!t)return;let a=t.href,d=t.origin!==location.origin;t.hasAttribute("download")||Ue.test(a)?y("file_download",{fileName:t.pathname.split("/").pop(),linkDomain:t.hostname||void 0}):(d||/^mailto:|^tel:/i.test(t.getAttribute("href")??""))&&y("click",{linkDomain:t.hostname||void 0,linkType:a.startsWith("mailto:")?"email":a.startsWith("tel:")?"phone":"outbound"})}),S(document,"play",e=>{let t=e.target;if(!(t instanceof HTMLVideoElement))return;let a=k.get(t);a||(a={milestones:new Set,watchedSeconds:0,lastMediaTime:t.currentTime,lastWallTime:Date.now(),started:!1},k.set(t,a)),a.started||(a.started=!0,y("video_start",G(t,a))),a.lastMediaTime=t.currentTime,a.lastWallTime=Date.now()},!0),S(document,"timeupdate",e=>{let t=e.target;if(!(t instanceof HTMLVideoElement))return;let a=k.get(t);a&&(pe(t,a),me(t,a))},!0),S(document,"ended",e=>{let t=e.target;if(!(t instanceof HTMLVideoElement))return;let a=k.get(t);a&&(pe(t,a),me(t,a),y("video_complete",G(t,a,100)))},!0),S(document,"visibilitychange",()=>{document.visibilityState==="hidden"?Y("hidden"):Pe()})}function xe(e){try{return e.currentSrc?new URL(e.currentSrc).origin+new URL(e.currentSrc).pathname:void 0}catch{return}}function ge(){if(!(p||q.state==="disabled"||T.analytics!=="granted"))try{let e=!c(n.anonymous),t=B();_e(),z(),Q(),p=!0,v++,W=location.href,J=new WeakSet,k=new WeakMap,ue(),e&&y("first_visit"),(!t||Date.now()-t.lastActivityAt>=we)&&y("session_start"),Ne(),ke(),S(window,"pagehide",()=>{Y("pagehide"),L(!0)}),$=window.setInterval(()=>{L()},3e3),w({state:"ready",error:void 0}),window.dispatchEvent(new Event("robot:ready"))}catch(e){Z(!1),w({state:"error",error:e instanceof Error?e.message:"Initialization failed"})}}function Z(e){p=!1,v++,O?.abort(),O=void 0,R=!1,$!==void 0&&window.clearInterval($),$=void 0;for(let t of F.splice(0).reverse())t();l=void 0,M=0,P=0,e&&(g=[],H(n.queue),H(n.anonymous),H(n.session))}function fe(e){if(q.state==="disabled")return;let t=JSON.stringify(T)!==JSON.stringify(e),a=p?c(n.anonymous):null;T={...e},o&&u(n.consent,JSON.stringify({...e,analytics:e.analytics==="granted"})),e.analytics!=="granted"?(Z(e.analytics==="denied"||!!a),w({state:"waiting_consent",error:void 0}),t&&a&&de(e,a)):(ge(),t&&p&&de(e,z()))}return{track:Ae,setConsent:fe,start:ge,restoreLegacyConsent:()=>{o&&T.analytics==="unknown"&&x(n.consent)?.analytics===!0&&fe({...x(n.consent),analytics:"granted"})},getStatus:()=>q,subscribe:e=>(V.add(e),()=>{V.delete(e)}),getAnonymousId:()=>p?c(n.anonymous):null,getSessionId:()=>p?Q():null,destroy:()=>{Z(!1),T={analytics:"unknown"},w({state:"disabled"}),V.clear()}}}var We=Symbol.for("sendermaster.browser.v1");function _(){if(typeof window>"u")return;let r=window;return r[We]||={subscribers:new Set}}function Je(r,o){let s=_();if(!s)return K;let n={...r,siteKey:r.siteKey?.trim()||"",apiHost:(r.apiHost||"https://api.sendermaster.com").replace(/\/$/,""),enabled:r.enabled!==!1},i=JSON.stringify(n);if(s.client&&s.fingerprint===i)return s.client.getStatus();s.client?.destroy(),s.fingerprint=i,s.client=Ee(n,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 Fe={init:r=>Je(r,!1),setConsent:r=>_()?.client?.setConsent(r),track(r,o){return _()?.client?.track(r,o)??{queued:!1,reason:"disabled"}},getStatus:()=>_()?.client?.getStatus()??K,subscribe(r){let o=_();return o?(o.subscribers.add(r),()=>{o.subscribers.delete(r)}):()=>{}},getAnonymousId:()=>_()?.client?.getAnonymousId()??null,getSessionId:()=>_()?.client?.getSessionId()??null,destroy(){let r=_();if(r){r.client?.destroy(),r.client=void 0,r.fingerprint=void 0;for(let o of r.subscribers)try{o()}catch{}}}};export{Fe as senderMaster};
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use strict";"use client";var re=Object.defineProperty;var He=Object.getOwnPropertyDescriptor;var Ue=Object.getOwnPropertyNames;var Je=Object.prototype.hasOwnProperty;var We=(n,s)=>{for(var a in s)re(n,a,{get:s[a],enumerable:!0})},ze=(n,s,a,r)=>{if(s&&typeof s=="object"||typeof s=="function")for(let i of Ue(s))!Je.call(n,i)&&i!==a&&re(n,i,{get:()=>s[i],enumerable:!(r=He(s,i))||r.enumerable});return n};var Fe=n=>ze(re({},"__esModule",{value:!0}),n);var dt={};We(dt,{SenderMasterProvider:()=>ot,senderMaster:()=>w,useBeginCheckout:()=>ct,useProductView:()=>it,useSenderMaster:()=>Ce});module.exports=Fe(dt);var I=require("react");var Be={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"}]},Qe=[{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"}],P=256,Xe=500,Se=100,we=50,Ee=3,_e=16*1024,Ye=/(password|passcode|secret|token|api.?key|card.?number|cvv|cvc|security.?code|ssn|passport)/i,Ge=Object.fromEntries(Object.entries(Be).map(([n,s])=>[n,s.map(a=>a.name)]));function Ze(n,s){let a=[];if(!J(s))return[{path:"properties",message:"must be an object"}];let r=s;for(let i of Object.keys(r))Ge[n].includes(i)||a.push({path:`properties.${i}`,message:"is not a supported standard field; place extension data under custom"});return n==="wishlist_added"?(v(r,"productId",a,!r.catalogProductId,P),v(r,"listName",a,!1,P)):n==="product_view"||n==="add_to_cart"?(v(r,"productId",a,!r.catalogProductId,P),v(r,"variantId",a,!1,P),oe(r,"amount",a,!1,!1),Te(r,a,!1),r.amount===void 0!=(r.currency===void 0)&&a.push({path:"properties.amount",message:"amount and currency must be provided together"}),n==="add_to_cart"&&ie(r,"quantity",a,!0,1)):n==="begin_checkout"?(v(r,"checkoutId",a,!0,P),oe(r,"amount",a,!0,!1),Te(r,a,!0),!Array.isArray(r.items)||r.items.length<1||r.items.length>Se?a.push({path:"properties.items",message:`must contain 1-${Se} items`}):r.items.forEach((i,c)=>et(i,c,a))):(v(r,"query",a,!0,Xe),ie(r,"resultsCount",a,!1,0)),["product_view","add_to_cart","wishlist_added"].includes(n)&&(v(r,"catalogProductId",a,!1,100),v(r,"catalogVariantId",a,!1,100),r.catalogVariantId&&!r.catalogProductId&&a.push({path:"properties.catalogVariantId",message:"requires catalogProductId"})),r.custom!==void 0&&tt(r.custom,a),a}function Me(n,s){let a=Ze(n,s);if(a.length)throw new ae(n,a);let r=s,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(a,r){super(`Invalid ${a} event: ${r.map(i=>`${i.path} ${i.message}`).join("; ")}`);this.eventName=a;this.issues=r;this.name="StandardEventValidationError"}eventName;issues};function et(n,s,a){let r=`properties.items[${s}]`;if(!J(n)){a.push({path:r,message:"must be an object"});return}let i=n,c=Qe.map(d=>d.name);for(let d of Object.keys(i))c.includes(d)||a.push({path:`${r}.${d}`,message:"is not supported"});v(i,"productId",a,!i.catalogProductId,P,r),v(i,"catalogProductId",a,!1,100,r),v(i,"catalogVariantId",a,!1,100,r),i.catalogVariantId&&!i.catalogProductId&&a.push({path:`${r}.catalogVariantId`,message:"requires catalogProductId"}),v(i,"variantId",a,!1,P,r),ie(i,"quantity",a,!0,1,r),oe(i,"amount",a,!1,!1,r)}function tt(n,s){if(!J(n)){s.push({path:"properties.custom",message:"must be an object"});return}let a=n;Object.keys(a).length>we&&s.push({path:"properties.custom",message:`must contain at most ${we} top-level fields`}),se(a,"properties.custom",1,s,new WeakSet);try{new TextEncoder().encode(JSON.stringify(a)).length>_e&&s.push({path:"properties.custom",message:`must be at most ${_e} bytes`})}catch{s.push({path:"properties.custom",message:"must be valid JSON data"})}}function se(n,s,a,r,i){if(a>Ee){r.push({path:s,message:`must not exceed ${Ee} 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:s,message:"must not contain circular references"});return}i.add(n)}if(Array.isArray(n)){n.forEach((c,d)=>se(c,`${s}[${d}]`,a+1,r,i));return}if(J(n)){Object.entries(n).forEach(([c,d])=>{(c.startsWith("_")||c.toLowerCase().startsWith("sm_"))&&r.push({path:`${s}.${c}`,message:"uses a reserved prefix"}),Ye.test(c)&&r.push({path:`${s}.${c}`,message:"must not contain secrets or sensitive payment/identity data"}),se(d,`${s}.${c}`,a+1,r,i)});return}r.push({path:s,message:"must contain JSON-compatible values only"})}}function J(n){if(!n||typeof n!="object"||Array.isArray(n))return!1;let s=Object.getPrototypeOf(n);return s===Object.prototype||s===null}function v(n,s,a,r,i,c="properties"){let d=n[s];if(d===void 0){r&&a.push({path:`${c}.${s}`,message:"is required"});return}(typeof d!="string"||d.length<1||d.length>i)&&a.push({path:`${c}.${s}`,message:`must be a string with 1-${i} characters`})}function oe(n,s,a,r,i,c="properties"){let d=n[s];if(d===void 0){r&&a.push({path:`${c}.${s}`,message:"is required"});return}(typeof d!="number"||!Number.isFinite(d)||(i?d<=0:d<0))&&a.push({path:`${c}.${s}`,message:i?"must be a positive finite number":"must be a non-negative finite number"})}function ie(n,s,a,r,i,c="properties"){let d=n[s];if(d===void 0){r&&a.push({path:`${c}.${s}`,message:"is required"});return}(typeof d!="number"||!Number.isInteger(d)||d<i)&&a.push({path:`${c}.${s}`,message:`must be an integer greater than or equal to ${i}`})}function Te(n,s,a){let r=n.currency;if(r===void 0){a&&s.push({path:"properties.currency",message:"is required"});return}(typeof r!="string"||!/^[A-Z]{3}$/.test(r))&&s.push({path:"properties.currency",message:"must be a 3-letter uppercase currency code"})}var qe=1800*1e3,nt=1440*60*1e3,rt=/\.(?:pdf|csv|docx?|xlsx?|pptx?|zip|rar|7z)(?:$|[?#])/i,V=Object.freeze({state:"disabled",consent:"unknown",queueLength:0,pageViewId:null});function ke(n,s=!1){let a=s?"robot_store":`sendermaster:${n.siteKey}`,r={anonymous:`${a}_anonymous_id`,session:`${a}_session`,consent:`${a}_consent`,queue:`${a}_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 A(e){try{return JSON.parse(c(e)??"null")}catch{return null}}let N=new Set,E={analytics:"unknown"},C={...V,state:n.enabled===!1||!n.siteKey?"disabled":"waiting_consent"},p=!1,S=0,L,K=!1,j,x=0,$=0,l,W=!1,z=location.href,F=new WeakSet,R=new WeakMap,g=[],B=[];function M(e={}){let t={...C,consent:E.analytics,queueLength:g.length,pageViewId:l?.id??null,...e};if(JSON.stringify(t)!==JSON.stringify(C)){C=Object.freeze(t);for(let o of N)try{o()}catch{}}}function _(e,t,o,u){let m=S,b=q=>{if(p&&S===m)try{o(q)}catch{}};e.addEventListener(t,b,u),B.push(()=>e.removeEventListener(t,b,u))}function ue(){return(n.apiHost??"https://api.sendermaster.com").replace(/\/$/,"")}function Q(){let e=c(r.anonymous);return e||(e=crypto.randomUUID(),d(r.anonymous,e)),e}function X(){let e=A(r.session);return e&&typeof e.id=="string"&&typeof e.lastActivityAt=="number"?e:void 0}function Y(){let e=Date.now(),t=X();if(!t||e-t.lastActivityAt>=qe){let o={id:crypto.randomUUID(),lastActivityAt:e};return d(r.session,JSON.stringify(o)),o.id}return t.lastActivityAt=e,d(r.session,JSON.stringify(t)),t.id}function G(){let e=Date.now();g=g.filter(t=>t.siteKey===n.siteKey&&e-Date.parse(t.event.occurredAt)<nt&&Date.parse(t.event.occurredAt)<=e+6e4).slice(-100)}function H(){G(),d(r.queue,JSON.stringify(g)),M()}function Ne(){let e=A(r.queue);Array.isArray(e)&&(g=e.flatMap(t=>{if(t?.event?.eventId&&typeof t.anonymousId=="string"&&typeof t.sessionId=="string")return[t];let o=c(r.anonymous),u=X();return s&&t?.eventId&&o&&u?[{siteKey:n.siteKey,anonymousId:o,sessionId:u.id,event:t}]:[]}),G())}function le(e){let t=new URL(e);return["email","token","password","access_token"].forEach(o=>t.searchParams.delete(o)),t.toString()}function pe(e){try{return new URL(e).origin}catch{return}}function xe(){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 Ve(e=location.pathname){return n.pageRules?.find(t=>e.startsWith(t.pathPrefix))?.pageType}function fe(){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={},o={}){if(!p)return;let{productId:u,catalogProductId:m,catalogVariantId:b,amount:q,currency:f,pageType:O,...D}=t,h={eventId:crypto.randomUUID(),name:e,occurredAt:new Date().toISOString(),url:o.url??le(location.href),path:o.path??location.pathname,...pe(document.referrer)?{referrer:pe(document.referrer)}:{},...typeof u=="string"?{productId:u}:{},...typeof m=="string"?{catalogProductId:m}:{},...typeof b=="string"?{catalogVariantId:b}:{},...typeof q=="number"?{amount:q}:{},...typeof f=="string"?{currency:f}:{},pageType:o.pageType??(typeof O=="string"?O:l?.pageType),pageViewId:o.pageViewId??l?.id,...o.engagedTimeMsec?{engagedTimeMsec:o.engagedTimeMsec}:{},...Object.keys(D).length?{properties:D}:{},context:xe()};return g.push({siteKey:n.siteKey,anonymousId:Q(),sessionId:Y(),event:JSON.parse(JSON.stringify(h))}),H(),g.length>=20&&U(),h.eventId}function $e(e,t){if(C.state==="disabled")return{queued:!1,reason:"disabled"};if(E.analytics!=="granted")return{queued:!1,reason:"consent_required"};if(!p)return{queued:!1,reason:"unavailable"};try{let o=Me(e,t),u=y(e,{...o.properties,productId:o.productId,catalogProductId:o.catalogProductId,catalogVariantId:o.catalogVariantId,amount:o.amount,currency:o.currency});return u?{queued:!0,eventId:u}:{queued:!1,reason:"unavailable"}}catch(o){return{queued:!1,reason:"invalid_event",message:o instanceof Error?o.message:"Invalid event"}}}async function U(e=!1){if(!p||K||(G(),M(),!g.length||!e&&Date.now()<x))return;let t=g[0],o=g.filter(f=>f.siteKey===t.siteKey&&f.anonymousId===t.anonymousId&&f.sessionId===t.sessionId).slice(0,20),u=JSON.stringify({siteKey:t.siteKey,anonymousId:t.anonymousId,sessionId:t.sessionId,events:o.map(f=>f.event)}),m=`${ue()}/v2/collect/events`;if(e)try{if(navigator.sendBeacon?.(m,new Blob([u],{type:"application/json"}))){H();return}}catch{}K=!0;let b=S,q=new AbortController;j=q;try{let f=await fetch(m,{method:"POST",headers:{"content-type":"application/json"},body:u,keepalive:!0,signal:q.signal});if(b!==S||!p)return;if(!f.ok){if(f.status===429||f.status>=500)throw new Error(`Collect HTTP ${f.status}`);let h=new Set(o.map(ne=>ne.event.eventId));g=g.filter(ne=>!h.has(ne.event.eventId)),H(),M({state:"error",error:`Collect HTTP ${f.status}: batch discarded`}),x=0,$=0;return}let O=await f.json();if(!Array.isArray(O.results))throw new Error("Collect response missing results");let D=new Set(O.results.filter(h=>h.status==="accepted"||h.status==="duplicate").map(h=>h.eventId));if(!o.every(h=>D.has(h.event.eventId)))throw new Error("Collect response incomplete");if(b!==S||!p)return;g=g.filter(h=>!D.has(h.event.eventId)),$=0,x=0,H(),M({state:"ready",error:void 0,lastDeliveredAt:new Date().toISOString()})}catch(f){if(b!==S||!p)return;$++,x=Date.now()+Math.min(6e4,3e3*2**Math.min($-1,5)),M({error:f instanceof Error?f.message:"Collect unavailable"})}finally{b===S&&(K=!1,j=void 0)}p&&g.length&&!x&&U()}function ge(e,t){let o=JSON.stringify({siteKey:n.siteKey,anonymousId:t,analyticsAllowed:e.analytics==="granted",marketingAllowed:e.marketing??!1,source:e.source??"sdk",policyVersion:e.policyVersion});try{fetch(`${ue()}/v2/collect/consent`,{method:"POST",headers:{"content-type":"application/json"},body:o,keepalive:!0}).then(u=>{if(!u.ok)throw new Error(`Consent HTTP ${u.status}`)}).catch(()=>{})}catch{}}function me(){l={id:crypto.randomUUID(),url:le(location.href),path:location.pathname,pageType:Ve(),enteredAt:new Date().toISOString(),visibleAt:document.visibilityState==="visible"?Date.now():0,activeMsec:0,reportedMsec:0,maxScrollPercent:fe()},W=!1,y("page_view")}function Re(){!p||!l?.visibleAt||(l.activeMsec+=Date.now()-l.visibleAt,l.visibleAt=0)}function Z(e){if(!p||!l)return;Re();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 Oe(){p&&l&&!l.visibleAt&&(l.visibleAt=Date.now())}function ye(){!p||location.href===z||(Z("navigation"),z=location.href,me())}function De(){let e=S,t=o=>{let u=history[o];history[o]=function(...b){let q=u.apply(this,b);return queueMicrotask(()=>{p&&S===e&&ye()}),q};let m=history[o];B.push(()=>{history[o]===m&&(history[o]=u)})};t("pushState"),t("replaceState"),_(window,"popstate",ye)}function Le(e){let t=je(e),o=Array.from(document.querySelectorAll("video")).indexOf(e);return{videoId:e.dataset.robotVideoId||e.id||t||`video:${location.pathname}:${o}`,videoTitle:e.dataset.robotVideoTitle||e.getAttribute("title")||void 0,productId:e.dataset.robotProductId||void 0,videoSrc:t}}function ee(e,t,o){return{...Le(e),watchedSeconds:Math.round(t.watchedSeconds*10)/10,durationSeconds:Math.round(e.duration*10)/10,...o!==void 0?{progressPercent:o}:{}}}function he(e,t){let o=Date.now(),u=e.currentTime-t.lastMediaTime,m=(o-t.lastWallTime)/1e3;u>0&&m>0&&u<=Math.max(3,m+1)&&(t.watchedSeconds+=Math.min(u,m+.5)),t.lastMediaTime=e.currentTime,t.lastWallTime=o}function Ie(e,t){if(!e.duration)return;let o=Math.min(100,Math.floor(e.currentTime/e.duration*100));for(let u of[25,50,75,100])o>=u&&!t.milestones.has(u)&&(t.milestones.add(u),y("video_progress",ee(e,t,u)))}function Ke(){_(window,"scroll",()=>{l&&(l.maxScrollPercent=Math.max(l.maxScrollPercent,fe()),!W&&l.maxScrollPercent>=90&&(W=!0,y("scroll",{percent:90})))},{passive:!0}),_(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}))}),_(document,"submit",e=>{let t=e.target;t instanceof HTMLFormElement&&y("form_submitted",{formId:t.id||void 0,formName:t.getAttribute("name")||void 0})}),_(document,"click",e=>{let t=e.target?.closest("a[href]");if(!t)return;let o=t.href,u=t.origin!==location.origin;t.hasAttribute("download")||rt.test(o)?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:o.startsWith("mailto:")?"email":o.startsWith("tel:")?"phone":"outbound"})}),_(document,"play",e=>{let t=e.target;if(!(t instanceof HTMLVideoElement))return;let o=R.get(t);o||(o={milestones:new Set,watchedSeconds:0,lastMediaTime:t.currentTime,lastWallTime:Date.now(),started:!1},R.set(t,o)),o.started||(o.started=!0,y("video_start",ee(t,o))),o.lastMediaTime=t.currentTime,o.lastWallTime=Date.now()},!0),_(document,"timeupdate",e=>{let t=e.target;if(!(t instanceof HTMLVideoElement))return;let o=R.get(t);o&&(he(t,o),Ie(t,o))},!0),_(document,"ended",e=>{let t=e.target;if(!(t instanceof HTMLVideoElement))return;let o=R.get(t);o&&(he(t,o),Ie(t,o),y("video_complete",ee(t,o,100)))},!0),_(document,"visibilitychange",()=>{document.visibilityState==="hidden"?Z("hidden"):Oe()})}function je(e){try{return e.currentSrc?new URL(e.currentSrc).origin+new URL(e.currentSrc).pathname:void 0}catch{return}}function be(){if(!(p||C.state==="disabled"||E.analytics!=="granted"))try{let e=!c(r.anonymous),t=X();Ne(),Q(),Y(),p=!0,S++,z=location.href,F=new WeakSet,R=new WeakMap,me(),e&&y("first_visit"),(!t||Date.now()-t.lastActivityAt>=qe)&&y("session_start"),Ke(),De(),_(window,"pagehide",()=>{Z("pagehide"),U(!0)}),L=window.setInterval(()=>{U()},3e3),M({state:"ready",error:void 0}),window.dispatchEvent(new Event("robot:ready"))}catch(e){te(!1),M({state:"error",error:e instanceof Error?e.message:"Initialization failed"})}}function te(e){p=!1,S++,j?.abort(),j=void 0,K=!1,L!==void 0&&window.clearInterval(L),L=void 0;for(let t of B.splice(0).reverse())t();l=void 0,x=0,$=0,e&&(g=[],T(r.queue),T(r.anonymous),T(r.session))}function ve(e){if(C.state==="disabled")return;let t=JSON.stringify(E)!==JSON.stringify(e),o=p?c(r.anonymous):null;E={...e},s&&d(r.consent,JSON.stringify({...e,analytics:e.analytics==="granted"})),e.analytics!=="granted"?(te(e.analytics==="denied"||!!o),M({state:"waiting_consent",error:void 0}),t&&o&&ge(e,o)):(be(),t&&p&&ge(e,Q()))}return{track:$e,setConsent:ve,start:be,restoreLegacyConsent:()=>{s&&E.analytics==="unknown"&&A(r.consent)?.analytics===!0&&ve({...A(r.consent),analytics:"granted"})},getStatus:()=>C,subscribe:e=>(N.add(e),()=>{N.delete(e)}),getAnonymousId:()=>p?c(r.anonymous):null,getSessionId:()=>p?Y():null,destroy:()=>{te(!1),E={analytics:"unknown"},M({state:"disabled"}),N.clear()}}}var at=Symbol.for("sendermaster.browser.v1");function k(){if(typeof window>"u")return;let n=window;return n[at]||={subscribers:new Set}}function st(n,s){let a=k();if(!a)return V;let r={...n,siteKey:n.siteKey?.trim()||"",apiHost:(n.apiHost||"https://api.sendermaster.com").replace(/\/$/,""),enabled:n.enabled!==!1},i=JSON.stringify(r);if(a.client&&a.fingerprint===i)return a.client.getStatus();a.client?.destroy(),a.fingerprint=i,a.client=ke(r,s),a.client.subscribe(()=>{for(let c of a.subscribers)try{c()}catch{}});for(let c of a.subscribers)try{c()}catch{}return a.client.getStatus()}var w={init:n=>st(n,!1),setConsent:n=>k()?.client?.setConsent(n),track(n,s){return k()?.client?.track(n,s)??{queued:!1,reason:"disabled"}},getStatus:()=>k()?.client?.getStatus()??V,subscribe(n){let s=k();return s?(s.subscribers.add(n),()=>{s.subscribers.delete(n)}):()=>{}},getAnonymousId:()=>k()?.client?.getAnonymousId()??null,getSessionId:()=>k()?.client?.getSessionId()??null,destroy(){let n=k();if(n){n.client?.destroy(),n.client=void 0,n.fingerprint=void 0;for(let s of n.subscribers)try{s()}catch{}}}};var Ae=(0,I.createContext)(!1),ce=0,de=0;function ot({children:n,analyticsConsent:s,marketingConsent:a=!1,consentSource:r="react",policyVersion:i,...c}){let d=JSON.stringify(c);return(0,I.useEffect)(()=>(ce++,de++,()=>{ce--;let T=++de;queueMicrotask(()=>{!ce&&T===de&&w.destroy()})}),[]),(0,I.useEffect)(()=>{w.init(JSON.parse(d))},[d]),(0,I.useEffect)(()=>{w.setConsent({analytics:s,marketing:a,source:r,policyVersion:i})},[d,s,a,r,i]),React.createElement(Ae.Provider,{value:!0},n)}function Ce(){let n=(0,I.useSyncExternalStore)(w.subscribe,w.getStatus,()=>V);return{...w,status:n}}function Pe(n,s,a,r,i){let c=(0,I.useContext)(Ae),{status:d}=Ce(),T=(0,I.useRef)(""),A=i?d.pageViewId:"",N=JSON.stringify(s);(0,I.useEffect)(()=>{if(!r){T.current="";return}if(!c||d.state!=="ready"||!a||!s)return;let E=`${A}:${a}`;T.current!==E&&w.track(n,s).queued&&(T.current=E)},[c,d.state,A,a,r,N])}function it(n,{viewKey:s,active:a=!0}){Pe("product_view",n,`${s}:${n?.productId??n?.catalogProductId??""}:${n?.variantId??n?.catalogVariantId??""}`,a,!0)}function ct(n,{checkoutKey:s,active:a=!0}){Pe("begin_checkout",n,s,a,!1)}
|
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 Ge,useContext as Ze,useEffect as J,useRef as et,useSyncExternalStore as tt}from"react";var Ke={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"}],C=256,He=500,ve=100,Se=50,we=3,Ee=16*1024,Ue=/(password|passcode|secret|token|api.?key|card.?number|cvv|cvc|security.?code|ssn|passport)/i,Je=Object.fromEntries(Object.entries(Ke).map(([r,o])=>[r,o.map(a=>a.name)]));function We(r,o){let a=[];if(!U(o))return[{path:"properties",message:"must be an object"}];let n=o;for(let i of Object.keys(n))Je[r].includes(i)||a.push({path:`properties.${i}`,message:"is not a supported standard field; place extension data under custom"});return r==="wishlist_added"?(b(n,"productId",a,!n.catalogProductId,C),b(n,"listName",a,!1,C)):r==="product_view"||r==="add_to_cart"?(b(n,"productId",a,!n.catalogProductId,C),b(n,"variantId",a,!1,C),se(n,"amount",a,!1,!1),_e(n,a,!1),n.amount===void 0!=(n.currency===void 0)&&a.push({path:"properties.amount",message:"amount and currency must be provided together"}),r==="add_to_cart"&&oe(n,"quantity",a,!0,1)):r==="begin_checkout"?(b(n,"checkoutId",a,!0,C),se(n,"amount",a,!0,!1),_e(n,a,!0),!Array.isArray(n.items)||n.items.length<1||n.items.length>ve?a.push({path:"properties.items",message:`must contain 1-${ve} items`}):n.items.forEach((i,c)=>ze(i,c,a))):(b(n,"query",a,!0,He),oe(n,"resultsCount",a,!1,0)),["product_view","add_to_cart","wishlist_added"].includes(r)&&(b(n,"catalogProductId",a,!1,100),b(n,"catalogVariantId",a,!1,100),n.catalogVariantId&&!n.catalogProductId&&a.push({path:"properties.catalogVariantId",message:"requires catalogProductId"})),n.custom!==void 0&&Fe(n.custom,a),a}function Te(r,o){let a=We(r,o);if(a.length)throw new re(r,a);let n=o,i={};for(let c of["variantId","quantity","checkoutId","items","query","resultsCount","listName","custom"])n[c]!==void 0&&(i[c]=n[c]);return{...typeof n.productId=="string"?{productId:n.productId}:{},...typeof n.catalogProductId=="string"?{catalogProductId:n.catalogProductId}:{},...typeof n.catalogVariantId=="string"?{catalogVariantId:n.catalogVariantId}:{},...typeof n.amount=="number"?{amount:n.amount}:{},...typeof n.currency=="string"?{currency:n.currency}:{},properties:i}}var re=class extends Error{constructor(a,n){super(`Invalid ${a} event: ${n.map(i=>`${i.path} ${i.message}`).join("; ")}`);this.eventName=a;this.issues=n;this.name="StandardEventValidationError"}eventName;issues};function ze(r,o,a){let n=`properties.items[${o}]`;if(!U(r)){a.push({path:n,message:"must be an object"});return}let i=r,c=je.map(d=>d.name);for(let d of Object.keys(i))c.includes(d)||a.push({path:`${n}.${d}`,message:"is not supported"});b(i,"productId",a,!i.catalogProductId,C,n),b(i,"catalogProductId",a,!1,100,n),b(i,"catalogVariantId",a,!1,100,n),i.catalogVariantId&&!i.catalogProductId&&a.push({path:`${n}.catalogVariantId`,message:"requires catalogProductId"}),b(i,"variantId",a,!1,C,n),oe(i,"quantity",a,!0,1,n),se(i,"amount",a,!1,!1,n)}function Fe(r,o){if(!U(r)){o.push({path:"properties.custom",message:"must be an object"});return}let a=r;Object.keys(a).length>Se&&o.push({path:"properties.custom",message:`must contain at most ${Se} top-level fields`}),ae(a,"properties.custom",1,o,new WeakSet);try{new TextEncoder().encode(JSON.stringify(a)).length>Ee&&o.push({path:"properties.custom",message:`must be at most ${Ee} bytes`})}catch{o.push({path:"properties.custom",message:"must be valid JSON data"})}}function ae(r,o,a,n,i){if(a>we){n.push({path:o,message:`must not exceed ${we} levels`});return}if(!(r===null||typeof r=="string"||typeof r=="boolean"||typeof r=="number"&&Number.isFinite(r))){if(typeof r=="object"&&r){if(i.has(r)){n.push({path:o,message:"must not contain circular references"});return}i.add(r)}if(Array.isArray(r)){r.forEach((c,d)=>ae(c,`${o}[${d}]`,a+1,n,i));return}if(U(r)){Object.entries(r).forEach(([c,d])=>{(c.startsWith("_")||c.toLowerCase().startsWith("sm_"))&&n.push({path:`${o}.${c}`,message:"uses a reserved prefix"}),Ue.test(c)&&n.push({path:`${o}.${c}`,message:"must not contain secrets or sensitive payment/identity data"}),ae(d,`${o}.${c}`,a+1,n,i)});return}n.push({path:o,message:"must contain JSON-compatible values only"})}}function U(r){if(!r||typeof r!="object"||Array.isArray(r))return!1;let o=Object.getPrototypeOf(r);return o===Object.prototype||o===null}function b(r,o,a,n,i,c="properties"){let d=r[o];if(d===void 0){n&&a.push({path:`${c}.${o}`,message:"is required"});return}(typeof d!="string"||d.length<1||d.length>i)&&a.push({path:`${c}.${o}`,message:`must be a string with 1-${i} characters`})}function se(r,o,a,n,i,c="properties"){let d=r[o];if(d===void 0){n&&a.push({path:`${c}.${o}`,message:"is required"});return}(typeof d!="number"||!Number.isFinite(d)||(i?d<=0:d<0))&&a.push({path:`${c}.${o}`,message:i?"must be a positive finite number":"must be a non-negative finite number"})}function oe(r,o,a,n,i,c="properties"){let d=r[o];if(d===void 0){n&&a.push({path:`${c}.${o}`,message:"is required"});return}(typeof d!="number"||!Number.isInteger(d)||d<i)&&a.push({path:`${c}.${o}`,message:`must be an integer greater than or equal to ${i}`})}function _e(r,o,a){let n=r.currency;if(n===void 0){a&&o.push({path:"properties.currency",message:"is required"});return}(typeof n!="string"||!/^[A-Z]{3}$/.test(n))&&o.push({path:"properties.currency",message:"must be a 3-letter uppercase currency code"})}var Me=1800*1e3,Be=1440*60*1e3,Qe=/\.(?:pdf|csv|docx?|xlsx?|pptx?|zip|rar|7z)(?:$|[?#])/i,x=Object.freeze({state:"disabled",consent:"unknown",queueLength:0,pageViewId:null});function qe(r,o=!1){let a=o?"robot_store":`sendermaster:${r.siteKey}`,n={anonymous:`${a}_anonymous_id`,session:`${a}_session`,consent:`${a}_consent`,queue:`${a}_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 _(e){i.delete(e);try{localStorage.removeItem(e)}catch{}}function k(e){try{return JSON.parse(c(e)??"null")}catch{return null}}let P=new Set,S={analytics:"unknown"},A={...x,state:r.enabled===!1||!r.siteKey?"disabled":"waiting_consent"},p=!1,v=0,D,L=!1,K,N=0,V=0,l,W=!1,z=location.href,F=new WeakSet,$=new WeakMap,g=[],B=[];function T(e={}){let t={...A,consent:S.analytics,queueLength:g.length,pageViewId:l?.id??null,...e};if(JSON.stringify(t)!==JSON.stringify(A)){A=Object.freeze(t);for(let s of P)try{s()}catch{}}}function w(e,t,s,u){let m=v,I=M=>{if(p&&v===m)try{s(M)}catch{}};e.addEventListener(t,I,u),B.push(()=>e.removeEventListener(t,I,u))}function de(){return(r.apiHost??"https://api.sendermaster.com").replace(/\/$/,"")}function Q(){let e=c(n.anonymous);return e||(e=crypto.randomUUID(),d(n.anonymous,e)),e}function X(){let e=k(n.session);return e&&typeof e.id=="string"&&typeof e.lastActivityAt=="number"?e:void 0}function Y(){let e=Date.now(),t=X();if(!t||e-t.lastActivityAt>=Me){let s={id:crypto.randomUUID(),lastActivityAt:e};return d(n.session,JSON.stringify(s)),s.id}return t.lastActivityAt=e,d(n.session,JSON.stringify(t)),t.id}function G(){let e=Date.now();g=g.filter(t=>t.siteKey===r.siteKey&&e-Date.parse(t.event.occurredAt)<Be&&Date.parse(t.event.occurredAt)<=e+6e4).slice(-100)}function j(){G(),d(n.queue,JSON.stringify(g)),T()}function Ce(){let e=k(n.queue);Array.isArray(e)&&(g=e.flatMap(t=>{if(t?.event?.eventId&&typeof t.anonymousId=="string"&&typeof t.sessionId=="string")return[t];let s=c(n.anonymous),u=X();return o&&t?.eventId&&s&&u?[{siteKey:r.siteKey,anonymousId:s,sessionId:u.id,event:t}]:[]}),G())}function ue(e){let t=new URL(e);return["email","token","password","access_token"].forEach(s=>t.searchParams.delete(s)),t.toString()}function le(e){try{return new URL(e).origin}catch{return}}function Pe(){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 Ne(e=location.pathname){return r.pageRules?.find(t=>e.startsWith(t.pathPrefix))?.pageType}function pe(){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={},s={}){if(!p)return;let{productId:u,catalogProductId:m,catalogVariantId:I,amount:M,currency:f,pageType:R,...O}=t,h={eventId:crypto.randomUUID(),name:e,occurredAt:new Date().toISOString(),url:s.url??ue(location.href),path:s.path??location.pathname,...le(document.referrer)?{referrer:le(document.referrer)}:{},...typeof u=="string"?{productId:u}:{},...typeof m=="string"?{catalogProductId:m}:{},...typeof I=="string"?{catalogVariantId:I}:{},...typeof M=="number"?{amount:M}:{},...typeof f=="string"?{currency:f}:{},pageType:s.pageType??(typeof R=="string"?R:l?.pageType),pageViewId:s.pageViewId??l?.id,...s.engagedTimeMsec?{engagedTimeMsec:s.engagedTimeMsec}:{},...Object.keys(O).length?{properties:O}:{},context:Pe()};return g.push({siteKey:r.siteKey,anonymousId:Q(),sessionId:Y(),event:JSON.parse(JSON.stringify(h))}),j(),g.length>=20&&H(),h.eventId}function xe(e,t){if(A.state==="disabled")return{queued:!1,reason:"disabled"};if(S.analytics!=="granted")return{queued:!1,reason:"consent_required"};if(!p)return{queued:!1,reason:"unavailable"};try{let s=Te(e,t),u=y(e,{...s.properties,productId:s.productId,catalogProductId:s.catalogProductId,catalogVariantId:s.catalogVariantId,amount:s.amount,currency:s.currency});return u?{queued:!0,eventId:u}:{queued:!1,reason:"unavailable"}}catch(s){return{queued:!1,reason:"invalid_event",message:s instanceof Error?s.message:"Invalid event"}}}async function H(e=!1){if(!p||L||(G(),T(),!g.length||!e&&Date.now()<N))return;let t=g[0],s=g.filter(f=>f.siteKey===t.siteKey&&f.anonymousId===t.anonymousId&&f.sessionId===t.sessionId).slice(0,20),u=JSON.stringify({siteKey:t.siteKey,anonymousId:t.anonymousId,sessionId:t.sessionId,events:s.map(f=>f.event)}),m=`${de()}/v2/collect/events`;if(e)try{if(navigator.sendBeacon?.(m,new Blob([u],{type:"application/json"}))){j();return}}catch{}L=!0;let I=v,M=new AbortController;K=M;try{let f=await fetch(m,{method:"POST",headers:{"content-type":"application/json"},body:u,keepalive:!0,signal:M.signal});if(I!==v||!p)return;if(!f.ok){if(f.status===429||f.status>=500)throw new Error(`Collect HTTP ${f.status}`);let h=new Set(s.map(ne=>ne.event.eventId));g=g.filter(ne=>!h.has(ne.event.eventId)),j(),T({state:"error",error:`Collect HTTP ${f.status}: batch discarded`}),N=0,V=0;return}let R=await f.json();if(!Array.isArray(R.results))throw new Error("Collect response missing results");let O=new Set(R.results.filter(h=>h.status==="accepted"||h.status==="duplicate").map(h=>h.eventId));if(!s.every(h=>O.has(h.event.eventId)))throw new Error("Collect response incomplete");if(I!==v||!p)return;g=g.filter(h=>!O.has(h.event.eventId)),V=0,N=0,j(),T({state:"ready",error:void 0,lastDeliveredAt:new Date().toISOString()})}catch(f){if(I!==v||!p)return;V++,N=Date.now()+Math.min(6e4,3e3*2**Math.min(V-1,5)),T({error:f instanceof Error?f.message:"Collect unavailable"})}finally{I===v&&(L=!1,K=void 0)}p&&g.length&&!N&&H()}function fe(e,t){let s=JSON.stringify({siteKey:r.siteKey,anonymousId:t,analyticsAllowed:e.analytics==="granted",marketingAllowed:e.marketing??!1,source:e.source??"sdk",policyVersion:e.policyVersion});try{fetch(`${de()}/v2/collect/consent`,{method:"POST",headers:{"content-type":"application/json"},body:s,keepalive:!0}).then(u=>{if(!u.ok)throw new Error(`Consent HTTP ${u.status}`)}).catch(()=>{})}catch{}}function ge(){l={id:crypto.randomUUID(),url:ue(location.href),path:location.pathname,pageType:Ne(),enteredAt:new Date().toISOString(),visibleAt:document.visibilityState==="visible"?Date.now():0,activeMsec:0,reportedMsec:0,maxScrollPercent:pe()},W=!1,y("page_view")}function Ve(){!p||!l?.visibleAt||(l.activeMsec+=Date.now()-l.visibleAt,l.visibleAt=0)}function Z(e){if(!p||!l)return;Ve();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 $e(){p&&l&&!l.visibleAt&&(l.visibleAt=Date.now())}function me(){!p||location.href===z||(Z("navigation"),z=location.href,ge())}function Re(){let e=v,t=s=>{let u=history[s];history[s]=function(...I){let M=u.apply(this,I);return queueMicrotask(()=>{p&&v===e&&me()}),M};let m=history[s];B.push(()=>{history[s]===m&&(history[s]=u)})};t("pushState"),t("replaceState"),w(window,"popstate",me)}function Oe(e){let t=Le(e),s=Array.from(document.querySelectorAll("video")).indexOf(e);return{videoId:e.dataset.robotVideoId||e.id||t||`video:${location.pathname}:${s}`,videoTitle:e.dataset.robotVideoTitle||e.getAttribute("title")||void 0,productId:e.dataset.robotProductId||void 0,videoSrc:t}}function ee(e,t,s){return{...Oe(e),watchedSeconds:Math.round(t.watchedSeconds*10)/10,durationSeconds:Math.round(e.duration*10)/10,...s!==void 0?{progressPercent:s}:{}}}function ye(e,t){let s=Date.now(),u=e.currentTime-t.lastMediaTime,m=(s-t.lastWallTime)/1e3;u>0&&m>0&&u<=Math.max(3,m+1)&&(t.watchedSeconds+=Math.min(u,m+.5)),t.lastMediaTime=e.currentTime,t.lastWallTime=s}function he(e,t){if(!e.duration)return;let s=Math.min(100,Math.floor(e.currentTime/e.duration*100));for(let u of[25,50,75,100])s>=u&&!t.milestones.has(u)&&(t.milestones.add(u),y("video_progress",ee(e,t,u)))}function De(){w(window,"scroll",()=>{l&&(l.maxScrollPercent=Math.max(l.maxScrollPercent,pe()),!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 s=t.href,u=t.origin!==location.origin;t.hasAttribute("download")||Qe.test(s)?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:s.startsWith("mailto:")?"email":s.startsWith("tel:")?"phone":"outbound"})}),w(document,"play",e=>{let t=e.target;if(!(t instanceof HTMLVideoElement))return;let s=$.get(t);s||(s={milestones:new Set,watchedSeconds:0,lastMediaTime:t.currentTime,lastWallTime:Date.now(),started:!1},$.set(t,s)),s.started||(s.started=!0,y("video_start",ee(t,s))),s.lastMediaTime=t.currentTime,s.lastWallTime=Date.now()},!0),w(document,"timeupdate",e=>{let t=e.target;if(!(t instanceof HTMLVideoElement))return;let s=$.get(t);s&&(ye(t,s),he(t,s))},!0),w(document,"ended",e=>{let t=e.target;if(!(t instanceof HTMLVideoElement))return;let s=$.get(t);s&&(ye(t,s),he(t,s),y("video_complete",ee(t,s,100)))},!0),w(document,"visibilitychange",()=>{document.visibilityState==="hidden"?Z("hidden"):$e()})}function Le(e){try{return e.currentSrc?new URL(e.currentSrc).origin+new URL(e.currentSrc).pathname:void 0}catch{return}}function Ie(){if(!(p||A.state==="disabled"||S.analytics!=="granted"))try{let e=!c(n.anonymous),t=X();Ce(),Q(),Y(),p=!0,v++,z=location.href,F=new WeakSet,$=new WeakMap,ge(),e&&y("first_visit"),(!t||Date.now()-t.lastActivityAt>=Me)&&y("session_start"),De(),Re(),w(window,"pagehide",()=>{Z("pagehide"),H(!0)}),D=window.setInterval(()=>{H()},3e3),T({state:"ready",error:void 0}),window.dispatchEvent(new Event("robot:ready"))}catch(e){te(!1),T({state:"error",error:e instanceof Error?e.message:"Initialization failed"})}}function te(e){p=!1,v++,K?.abort(),K=void 0,L=!1,D!==void 0&&window.clearInterval(D),D=void 0;for(let t of B.splice(0).reverse())t();l=void 0,N=0,V=0,e&&(g=[],_(n.queue),_(n.anonymous),_(n.session))}function be(e){if(A.state==="disabled")return;let t=JSON.stringify(S)!==JSON.stringify(e),s=p?c(n.anonymous):null;S={...e},o&&d(n.consent,JSON.stringify({...e,analytics:e.analytics==="granted"})),e.analytics!=="granted"?(te(e.analytics==="denied"||!!s),T({state:"waiting_consent",error:void 0}),t&&s&&fe(e,s)):(Ie(),t&&p&&fe(e,Q()))}return{track:xe,setConsent:be,start:Ie,restoreLegacyConsent:()=>{o&&S.analytics==="unknown"&&k(n.consent)?.analytics===!0&&be({...k(n.consent),analytics:"granted"})},getStatus:()=>A,subscribe:e=>(P.add(e),()=>{P.delete(e)}),getAnonymousId:()=>p?c(n.anonymous):null,getSessionId:()=>p?Y():null,destroy:()=>{te(!1),S={analytics:"unknown"},T({state:"disabled"}),P.clear()}}}var Xe=Symbol.for("sendermaster.browser.v1");function q(){if(typeof window>"u")return;let r=window;return r[Xe]||={subscribers:new Set}}function Ye(r,o){let a=q();if(!a)return x;let n={...r,siteKey:r.siteKey?.trim()||"",apiHost:(r.apiHost||"https://api.sendermaster.com").replace(/\/$/,""),enabled:r.enabled!==!1},i=JSON.stringify(n);if(a.client&&a.fingerprint===i)return a.client.getStatus();a.client?.destroy(),a.fingerprint=i,a.client=qe(n,o),a.client.subscribe(()=>{for(let c of a.subscribers)try{c()}catch{}});for(let c of a.subscribers)try{c()}catch{}return a.client.getStatus()}var E={init:r=>Ye(r,!1),setConsent:r=>q()?.client?.setConsent(r),track(r,o){return q()?.client?.track(r,o)??{queued:!1,reason:"disabled"}},getStatus:()=>q()?.client?.getStatus()??x,subscribe(r){let o=q();return o?(o.subscribers.add(r),()=>{o.subscribers.delete(r)}):()=>{}},getAnonymousId:()=>q()?.client?.getAnonymousId()??null,getSessionId:()=>q()?.client?.getSessionId()??null,destroy(){let r=q();if(r){r.client?.destroy(),r.client=void 0,r.fingerprint=void 0;for(let o of r.subscribers)try{o()}catch{}}}};var ke=Ge(!1),ie=0,ce=0;function gt({children:r,analyticsConsent:o,marketingConsent:a=!1,consentSource:n="react",policyVersion:i,...c}){let d=JSON.stringify(c);return J(()=>(ie++,ce++,()=>{ie--;let _=++ce;queueMicrotask(()=>{!ie&&_===ce&&E.destroy()})}),[]),J(()=>{E.init(JSON.parse(d))},[d]),J(()=>{E.setConsent({analytics:o,marketing:a,source:n,policyVersion:i})},[d,o,a,n,i]),React.createElement(ke.Provider,{value:!0},r)}function nt(){let r=tt(E.subscribe,E.getStatus,()=>x);return{...E,status:r}}function Ae(r,o,a,n,i){let c=Ze(ke),{status:d}=nt(),_=et(""),k=i?d.pageViewId:"",P=JSON.stringify(o);J(()=>{if(!n){_.current="";return}if(!c||d.state!=="ready"||!a||!o)return;let S=`${k}:${a}`;_.current!==S&&E.track(r,o).queued&&(_.current=S)},[c,d.state,k,a,n,P])}function mt(r,{viewKey:o,active:a=!0}){Ae("product_view",r,`${o}:${r?.productId??r?.catalogProductId??""}:${r?.variantId??r?.catalogVariantId??""}`,a,!0)}function yt(r,{checkoutKey:o,active:a=!0}){Ae("begin_checkout",r,o,a,!1)}export{gt as SenderMasterProvider,E as senderMaster,yt as useBeginCheckout,mt as useProductView,nt as useSenderMaster};
|
|
@@ -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,40 @@
|
|
|
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
|
+
/** Safe to import during SSR; browser work starts only at init + granted consent. */
|
|
4
|
+
export declare const senderMaster: {
|
|
5
|
+
init: (config: Config) => Readonly<{
|
|
6
|
+
state: "disabled" | "waiting_consent" | "ready" | "error";
|
|
7
|
+
consent: import("./core").AnalyticsConsent;
|
|
8
|
+
queueLength: number;
|
|
9
|
+
pageViewId: string | null;
|
|
10
|
+
error?: string;
|
|
11
|
+
lastDeliveredAt?: string;
|
|
12
|
+
}>;
|
|
13
|
+
setConsent: (value: Consent) => void | undefined;
|
|
14
|
+
track<Name extends StandardEventName>(name: Name, properties: StandardEventInputMap[Name]): TrackResult;
|
|
15
|
+
getStatus: () => Readonly<{
|
|
16
|
+
state: "disabled" | "waiting_consent" | "ready" | "error";
|
|
17
|
+
consent: import("./core").AnalyticsConsent;
|
|
18
|
+
queueLength: number;
|
|
19
|
+
pageViewId: string | null;
|
|
20
|
+
error?: string;
|
|
21
|
+
lastDeliveredAt?: string;
|
|
22
|
+
}>;
|
|
23
|
+
subscribe(fn: () => void): () => void;
|
|
24
|
+
getAnonymousId: () => string | null;
|
|
25
|
+
getSessionId: () => string | null;
|
|
26
|
+
destroy(): void;
|
|
27
|
+
};
|
|
28
|
+
/** Internal compatibility entry; keep the old public methods and storage names. */
|
|
29
|
+
export declare function installLegacyPixel(config: Config): {
|
|
30
|
+
start: () => void | undefined;
|
|
31
|
+
track: <Name extends StandardEventName>(name: Name, properties: StandardEventInputMap[Name]) => TrackResult;
|
|
32
|
+
setConsent: (value: {
|
|
33
|
+
analytics: boolean;
|
|
34
|
+
marketing?: boolean;
|
|
35
|
+
source?: string;
|
|
36
|
+
policyVersion?: string;
|
|
37
|
+
}) => void | undefined;
|
|
38
|
+
getAnonymousId: () => string | null;
|
|
39
|
+
getSessionId: () => string | null;
|
|
40
|
+
};
|
|
@@ -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,54 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
import { type Config, type AnalyticsConsent, type Consent, type StandardEventInputMap } from './browser';
|
|
3
|
+
export { senderMaster } from './browser';
|
|
4
|
+
export type { Config, Consent, AnalyticsConsent, Status, TrackResult, StandardEventInputMap, StandardEventName, CheckoutItem } from './browser';
|
|
5
|
+
export type SenderMasterProviderProps = Config & {
|
|
6
|
+
children?: ReactNode;
|
|
7
|
+
analyticsConsent: AnalyticsConsent;
|
|
8
|
+
marketingConsent?: boolean;
|
|
9
|
+
consentSource?: string;
|
|
10
|
+
policyVersion?: string;
|
|
11
|
+
};
|
|
12
|
+
export declare function SenderMasterProvider({ children, analyticsConsent, 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: Consent) => void | undefined;
|
|
31
|
+
track<Name extends import("./browser").StandardEventName>(name: Name, properties: StandardEventInputMap[Name]): import("./browser").TrackResult;
|
|
32
|
+
getStatus: () => Readonly<{
|
|
33
|
+
state: "disabled" | "waiting_consent" | "ready" | "error";
|
|
34
|
+
consent: AnalyticsConsent;
|
|
35
|
+
queueLength: number;
|
|
36
|
+
pageViewId: string | null;
|
|
37
|
+
error?: string;
|
|
38
|
+
lastDeliveredAt?: string;
|
|
39
|
+
}>;
|
|
40
|
+
subscribe(fn: () => void): () => void;
|
|
41
|
+
getAnonymousId: () => string | null;
|
|
42
|
+
getSessionId: () => string | null;
|
|
43
|
+
destroy(): void;
|
|
44
|
+
};
|
|
45
|
+
type ViewOptions = {
|
|
46
|
+
viewKey: string;
|
|
47
|
+
active?: boolean;
|
|
48
|
+
};
|
|
49
|
+
type CheckoutOptions = {
|
|
50
|
+
checkoutKey: string;
|
|
51
|
+
active?: boolean;
|
|
52
|
+
};
|
|
53
|
+
export declare function useProductView(properties: StandardEventInputMap['product_view'] | null | undefined, { viewKey, active }: ViewOptions): void;
|
|
54
|
+
export declare function useBeginCheckout(properties: StandardEventInputMap['begin_checkout'] | null | undefined, { checkoutKey, active }: CheckoutOptions): void;
|
package/package.json
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
{
|
|
2
|
-
"name": "@sendermaster/react",
|
|
3
|
-
"
|
|
4
|
-
"
|
|
5
|
-
|
|
6
|
-
}
|
|
2
|
+
"name": "@sendermaster/react", "version": "0.1.0", "description": "SenderMaster React integration with an embedded browser SDK", "license": "UNLICENSED",
|
|
3
|
+
"type": "module", "main": "./dist/index.cjs", "module": "./dist/index.js", "types": "./dist/index.d.ts",
|
|
4
|
+
"exports": {
|
|
5
|
+
".": { "types": "./dist/index.d.ts", "import": "./dist/index.js", "require": "./dist/index.cjs" },
|
|
6
|
+
"./browser": { "types": "./dist/browser.d.ts", "import": "./dist/browser.js", "require": "./dist/browser.cjs" }
|
|
7
|
+
},
|
|
8
|
+
"files": ["dist", "README.md", "CHANGELOG.md"], "sideEffects": false,
|
|
9
|
+
"peerDependencies": { "react": "^18.2.0" },
|
|
10
|
+
"devDependencies": { "@types/react": "^18.3.0", "react": "^18.2.0" }
|
|
11
|
+
}
|