@bluenath/engage 2.0.1 → 2.0.2
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/dist/core/Analytics.d.ts +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.js +47 -6
- package/dist/types/index.d.ts +5 -0
- package/package.json +1 -1
package/dist/core/Analytics.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ export declare class EngagePro {
|
|
|
9
9
|
identify: (userId: string, traits?: Record<string, unknown>) => void;
|
|
10
10
|
page: (name?: string, properties?: Record<string, unknown>) => void;
|
|
11
11
|
track: (eventName: string, properties?: Record<string, unknown>, intelligence?: Partial<AnalyticsEvent>) => void;
|
|
12
|
-
trackRevenue: (
|
|
12
|
+
trackRevenue: (amount: number | string, properties?: Record<string, unknown>, intelligence?: Partial<AnalyticsEvent>) => void;
|
|
13
13
|
private parseRef;
|
|
14
14
|
private processEvent;
|
|
15
15
|
}
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var t=Object.defineProperty,e=(e,n,i)=>((e,n,i)=>n in e?t(e,n,{enumerable:!0,configurable:!0,writable:!0,value:i}):e[n]=i)(e,"symbol"!=typeof n?n+"":n,i);Object.defineProperties(exports,{t:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const n=require("react/jsx-runtime"),i=require("react");let s;const r=new Uint8Array(16);function o(){if(!s&&(s="undefined"!=typeof crypto&&crypto.getRandomValues&&crypto.getRandomValues.bind(crypto),!s))throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");return s(r)}const a=[];for(let E=0;E<256;++E)a.push((E+256).toString(16).slice(1));const c={randomUUID:"undefined"!=typeof crypto&&crypto.randomUUID&&crypto.randomUUID.bind(crypto)};function d(t,e,n){if(c.randomUUID&&!t)return c.randomUUID();const i=(t=t||{}).random||(t.rng||o)();return i[6]=15&i[6]|64,i[8]=63&i[8]|128,function(t,e=0){return a[t[e+0]]+a[t[e+1]]+a[t[e+2]]+a[t[e+3]]+"-"+a[t[e+4]]+a[t[e+5]]+"-"+a[t[e+6]]+a[t[e+7]]+"-"+a[t[e+8]]+a[t[e+9]]+"-"+a[t[e+10]]+a[t[e+11]]+a[t[e+12]]+a[t[e+13]]+a[t[e+14]]+a[t[e+15]]}(i)}const h=t=>{let e=2166136261;const n=t.length;for(let i=0;i<n;i++)e^=t.charCodeAt(i),e+=(e<<1)+(e<<4)+(e<<7)+(e<<8)+(e<<24);return("0000000"+(e>>>0).toString(16)).substr(-8)};class l{constructor(t="local"){e(this,"memoryStore",{}),e(this,"keyPrefix","engage_"),e(this,"domain"),this.type=t,this.domain=this.getCookieDomain()}getItem(t){const e=this.keyPrefix+t;if(this.memoryStore.hasOwnProperty(e))return this.memoryStore[e];try{if("local"===this.type&&this.isBrowser())return window.localStorage.getItem(e);if("cookie"===this.type&&this.isBrowser())return this.getCookie(e)}catch(n){return null}return null}setItem(t,e){const n=this.keyPrefix+t;this.memoryStore[n]=e;try{"local"===this.type&&this.isBrowser()?window.localStorage.setItem(n,e):"cookie"===this.type&&this.isBrowser()&&this.setCookie(n,e,365)}catch(i){this.isQuotaError(i)&&(this.type="memory")}}removeItem(t){const e=this.keyPrefix+t;delete this.memoryStore[e];try{"local"===this.type&&this.isBrowser()?window.localStorage.removeItem(e):"cookie"===this.type&&this.isBrowser()&&this.setCookie(e,"",-1)}catch(n){}}getCookie(t){const e=t+"=",n=document.cookie.split(";");for(let i=0;i<n.length;i++){let t=n[i];for(;" "===t.charAt(0);)t=t.substring(1,t.length);if(0===t.indexOf(e))return decodeURIComponent(t.substring(e.length,t.length))}return null}setCookie(t,e,n){let i="";if(n){const t=new Date;t.setTime(t.getTime()+24*n*60*60*1e3),i="; expires="+t.toUTCString()}document.cookie=`${t}=${encodeURIComponent(e)}${i}; path=/; domain=${this.domain}; SameSite=Lax; Secure`}getCookieDomain(){if(!this.isBrowser())return"";const t=window.location.hostname,e=t.split(".");return 1===e.length||"localhost"===t?"":e.length>2?"."+e.slice(-2).join("."):"."+t}isBrowser(){try{return"undefined"!=typeof window&&void 0!==window.document}catch(t){return!1}}isQuotaError(t){return t instanceof DOMException&&(22===t.code||1014===t.code||"QuotaExceededError"===t.name||"NS_ERROR_DOM_QUOTA_REACHED"===t.name)}}class u{constructor(t){e(this,"storage"),e(this,"SESSION_TIMEOUT",18e5),e(this,"deviceId"),e(this,"sessionId"),e(this,"userId",null),e(this,"currentUrl"),e(this,"referrer"),this.storage=new l(t.persistence),this.deviceId=this.getOrSetDeviceId(),this.sessionId="",this.manageSession(),"undefined"!=typeof window?(this.currentUrl=window.location.href,this.referrer=document.referrer,this.listenToHistory()):(this.currentUrl="",this.referrer="")}getOrSetDeviceId(){const t=this.storage.getItem("device_id");if(t)return t;const e=(()=>{if("undefined"==typeof window)return"server-side-id";const t=navigator,e=window.screen,n={userAgent:t.userAgent||"",screenRes:`${e.width}x${e.height}`,colorDepth:e.colorDepth||0,timezone:(new Date).getTimezoneOffset(),language:t.language||"en-US",platform:t.platform||"unknown",hardwareConcurrency:t.hardwareConcurrency||1,deviceMemory:t.deviceMemory||0},i=[n.platform,n.language,n.screenRes,n.colorDepth,n.timezone,n.hardwareConcurrency,n.deviceMemory].join("|");return`${h(i)}-${h(n.userAgent)}`})();return this.storage.setItem("device_id",e),e}manageSession(){const t=Date.now(),e=this.storage.getItem("session_id"),n=parseInt(this.storage.getItem("last_activity")||"0");if(!e||t-n>this.SESSION_TIMEOUT?(this.sessionId=`sess_${t}_${Math.random().toString(36).substr(2,9)}`,this.storage.setItem("session_id",this.sessionId)):this.sessionId=e,this.storage.setItem("last_activity",t.toString()),"undefined"!=typeof window){const t=()=>this.storage.setItem("last_activity",Date.now().toString());window.addEventListener("click",t),window.addEventListener("scroll",t)}}listenToHistory(){const t=history.pushState;history.pushState=(...e)=>{t.apply(history,e),this.handleUrlChange()},window.addEventListener("popstate",()=>this.handleUrlChange())}handleUrlChange(){const t=window.location.href;t!==this.currentUrl&&(this.referrer=this.currentUrl,this.currentUrl=t)}getPayload(){var t;return{library:{name:"@engagepro/analytics",version:"2.0.0"},user:{anonymousId:this.deviceId,id:this.userId},session:{id:this.sessionId,startTime:parseInt(this.sessionId.split("_")[1]||Date.now().toString())},page:{path:"undefined"!=typeof window?window.location.pathname:"",referrer:this.referrer,title:"undefined"!=typeof document?document.title:"",search:"undefined"!=typeof window?window.location.search:"",url:this.currentUrl},network:{online:"undefined"==typeof navigator||navigator.onLine,downlink:null==(t=navigator.connection)?void 0:t.downlink},screen:{width:"undefined"!=typeof screen?screen.width:0,height:"undefined"!=typeof screen?screen.height:0,density:"undefined"!=typeof window?window.devicePixelRatio:1},device:{fingerprint:this.deviceId,type:this.getDeviceType(),userAgent:"undefined"!=typeof navigator?navigator.userAgent:"server"},locale:"undefined"!=typeof navigator?navigator.language:"en-US",timezone:Intl.DateTimeFormat().resolvedOptions().timeZone}}getDeviceType(){if("undefined"==typeof navigator)return"desktop";const t=navigator.userAgent;return/(tablet|ipad|playbook|silk)|(android(?!.*mobi))/i.test(t)?"tablet":/Mobile|Android|iP(hone|od)|IEMobile|BlackBerry|Kindle|Silk-Accelerated/.test(t)?"mobile":"desktop"}}class f{constructor(t){e(this,"queue",[]),e(this,"storage"),e(this,"transport"),e(this,"STORAGE_KEY","engage_queue_v1"),e(this,"isFlushing",!1),e(this,"flushInterval"),e(this,"retryCount",0),this.transport=t,this.storage=new l("local"),this.load(),"undefined"!=typeof window&&(window.addEventListener("online",()=>{this.retryCount=0,this.flush()}),window.addEventListener("visibilitychange",()=>{"hidden"===document.visibilityState&&this.flush()})),this.startTimer()}startTimer(){this.flushInterval&&clearInterval(this.flushInterval);const t=3e3*Math.pow(2,this.retryCount);this.flushInterval=setInterval(()=>{this.flush()},Math.min(t,3e4))}enqueue(t){this.queue.push(t),this.save(),(this.queue.length>=10||"PURCHASE"===t.standardEvent)&&this.flush()}save(){this.storage.setItem(this.STORAGE_KEY,JSON.stringify(this.queue))}load(){const t=this.storage.getItem(this.STORAGE_KEY);if(t)try{this.queue=JSON.parse(t)}catch(e){this.queue=[]}}async flush(){if(0===this.queue.length||this.isFlushing)return;if("undefined"!=typeof navigator&&!navigator.onLine)return;this.isFlushing=!0;const t=[...this.queue];this.queue=[],this.save();try{if(!(await this.transport.send(t)))throw new Error("Server rejected batch");this.retryCount=0,this.startTimer()}catch(e){this.queue=[...t,...this.queue],this.save(),this.retryCount++,this.startTimer()}finally{this.isFlushing=!1}}}class p{constructor(t){this.apiEndpoint=t}async send(t){const e=JSON.stringify({batch:t,sentAt:(new Date).toISOString()});if("undefined"!=typeof navigator&&navigator.sendBeacon&&e.length<6e4){const t=new Blob([e],{type:"application/json"});if(navigator.sendBeacon(this.apiEndpoint,t))return!0}try{return(await fetch(this.apiEndpoint,{method:"POST",headers:{"Content-Type":"application/json"},body:e,keepalive:!0})).ok}catch(n){return!1}}}const w="https://engage-api.bluenath.com/api/v1/tracking/ingest",y=new Set(["localhost","127.0.0.1"]);class v{constructor(t){e(this,"config"),e(this,"context"),e(this,"queue"),e(this,"transport"),e(this,"identify",(t,e)=>{this.context.userId=t,this.processEvent({event:"Identify",properties:{traits:e},standardEvent:"LOGIN",intent:"identity",confidence:1})}),e(this,"page",(t,e)=>{const n=this.context.getPayload().page;this.processEvent({event:t||n.title||"Unknown Page",properties:{path:n.path,referrer:n.referrer,title:n.title,...e},standardEvent:"PAGE_VIEW",intent:"navigation",confidence:1})}),e(this,"track",(t,e,n)=>{this.processEvent({event:t,properties:e||{},...n})}),e(this,"trackRevenue",(t,e,n)=>{this.track("PURCHASE",{...e||{},value:Math.round(t),valuePaise:Math.round(t)},{standardEvent:"PURCHASE",intent:"commerce",confidence:1,...n})}),this.config=t,this.transport=new p((t=>{if(!t)return w;try{const e=new URL(t);return e.hostname.endsWith("bluenath.com")||y.has(e.hostname)?(e.pathname="/api/v1/tracking/ingest",e.search="",e.hash="",e.toString()):w}catch{return w}})(t.apiHost)),this.context=new u({persistence:t.tracking.useCookies?"cookie":"local"}),this.queue=new f(this.transport)}parseRef(t){if(!t)return{};const e=t.match(/^camp_([^_]+)_cr_([^_]+)$/);return e?{campaignId:e[1],creatorId:e[2]}:{}}processEvent(t){const e=this.context.getPayload(),n=t.properties.ref,i=("string"==typeof n?n:void 0)||new URLSearchParams(e.page.search||"").get("ref")||void 0,s=this.parseRef(i),r=t.properties.valuePaise??t.properties.amountPaise??t.properties.value??t.properties.amount,o=Number(r),a=t.properties.campaignId,c=t.properties.creatorId,h=t.properties.currency,l={event:t.event,properties:t.properties,standardEvent:t.standardEvent,intent:t.intent,confidence:t.confidence,rawLabel:t.rawLabel,timestamp:(new Date).toISOString(),messageId:d(),writeKey:this.config.writeKey,ref:i,campaignId:("string"==typeof a?a:void 0)||s.campaignId,creatorId:("string"==typeof c?c:void 0)||s.creatorId,value:Number.isFinite(o)?Math.round(o):void 0,valuePaise:Number.isFinite(o)?Math.round(o):void 0,currency:("string"==typeof h?h:void 0)||"INR",userId:e.user.id||void 0,anonymousId:e.user.anonymousId,context:e};this.config.debug,this.queue.enqueue(l)}}class m{constructor(t){e(this,"analytics"),e(this,"metrics",{}),this.analytics=t,"undefined"!=typeof window&&"PerformanceObserver"in window&&this.observe()}observe(){try{new PerformanceObserver(t=>{for(const e of t.getEntries()){const t=e;t.hadRecentInput||(this.metrics.cls=(this.metrics.cls||0)+t.value)}}).observe({type:"layout-shift",buffered:!0}),new PerformanceObserver(t=>{const e=t.getEntries(),n=e[e.length-1];this.metrics.lcp=n.renderTime||n.loadTime,this.logMetric("LCP",this.metrics.lcp)}).observe({type:"largest-contentful-paint",buffered:!0}),new PerformanceObserver(t=>{const e=t.getEntries()[0];e&&(this.metrics.fid=e.processingStart-e.startTime,this.logMetric("FID",this.metrics.fid))}).observe({type:"first-input",buffered:!0}),window.addEventListener("visibilitychange",()=>{"hidden"===document.visibilityState&&this.metrics.cls&&this.logMetric("CLS",this.metrics.cls)})}catch(t){}}logMetric(t,e){e<0||this.analytics.track(`Core Web Vital: ${t}`,{metric:t,value:Math.round(e)},{standardEvent:"PERFORMANCE",intent:"performance",confidence:1,rawLabel:`${t}: ${Math.round(e)}ms`})}}const g=i.createContext(null);let b=null;exports.EngageProProvider=({children:t,...e})=>{const s=i.useRef(null),r=i.useRef(null);s.current||(s.current=new v(e),"undefined"!=typeof window&&new m(s.current));const o=s.current;return i.useEffect(()=>{if(!e.tracking.autoTrack)return;const t=t=>{const e=t.target.closest('button, a, input[type="submit"], [data-track], .clickable');if(e){const t=Date.now(),n=r.current;n&&n.el===e&&t-n.ts<500?(n.count++,n.ts=t,3===n.count&&(o.track("Rage Click detected",{element:e.tagName},{standardEvent:"RAGE_CLICK",intent:"frustration",confidence:1}),r.current=null)):r.current={el:e,count:1,ts:t};const i=(t=>{let e=(t.innerText||t.value||t.getAttribute("aria-label")||"").trim();if(!e){const n=t.querySelector("img");n&&n.alt&&(e=n.alt);const i=t.querySelector("title");i&&(e=i.textContent||"")}const n=e.slice(0,100),i=n.toLowerCase(),s=(t.id||"").toLowerCase(),r=t.href||"";return/add to (cart|bag)|buy now/.test(i)||s.includes("add-to-cart")?{standard:"ADD_TO_CART",intent:"commerce",label:n,confidence:.9}:/checkout|proceed/.test(i)||r.includes("/checkout")?{standard:"INITIATE_CHECKOUT",intent:"commerce",label:n,confidence:.9}:/place order|pay now/.test(i)||s.includes("place-order")?{standard:"PURCHASE",intent:"commerce",label:n,confidence:.95}:/cancel order/.test(i)||s.includes("cancel")?{standard:"ORDER_CANCEL",intent:"lifecycle",label:n,confidence:.85}:/refund|return/.test(i)||s.includes("refund")?{standard:"ORDER_REFUND",intent:"lifecycle",label:n,confidence:.85}:/track package|shipping/.test(i)?{standard:"TRACK_PACKAGE",intent:"lifecycle",label:n,confidence:.8}:/write review/.test(i)||i.includes("star")&&/^[1-5]/.test(i)?{standard:"RATE_PRODUCT",intent:"engagement",label:n,confidence:.8}:i.includes("search")||s.includes("search")?{standard:"SEARCH",intent:"search",label:n,confidence:.7}:{standard:"GENERIC",intent:"interaction",label:n,confidence:.5}})(e),s="A"===e.tagName;o.track("Interaction",{element:e.tagName.toLowerCase(),id:e.id,destination:s?e.href:void 0},{standardEvent:i.standard,intent:i.intent,rawLabel:i.label,confidence:i.confidence})}},n=t=>{const e=t.target;(t=>"password"===t.getAttribute("type")||"hidden"===t.getAttribute("type")||/password|cvc|card|cc-num|ssn|credit|hidden/i.test(t.getAttribute("name")||t.id||""))(e)||"focusin"!==t.type||e.dataset.tracked||(e.dataset.tracked="true",o.track("Form Start",{field:e.name||e.id},{standardEvent:"FORM_START",intent:"identity"}))},i=()=>{const t=new URLSearchParams(window.location.search);t.has("q")&&o.track("Search Query",{query:t.get("q")},{standardEvent:"SEARCH",intent:"search"}),requestAnimationFrame(()=>o.page())},s=history.pushState;return history.pushState=(...t)=>{s.apply(history,t),i()},window.addEventListener("popstate",i),window.addEventListener("click",t,!0),window.addEventListener("focusin",n,!0),i(),()=>{history.pushState=s,window.removeEventListener("popstate",i),window.removeEventListener("click",t,!0),window.removeEventListener("focusin",n,!0)}},[e.tracking.autoTrack]),n.jsx(g.Provider,{value:o,children:t})},exports.default=v,exports.init=t=>(b||(b=new v(t)),b),exports.useAnalytics=()=>{const t=i.useContext(g);if(!t)throw new Error("useAnalytics must be used within EngageProProvider");return t};
|
|
1
|
+
"use strict";var t=Object.defineProperty,e=(e,n,i)=>((e,n,i)=>n in e?t(e,n,{enumerable:!0,configurable:!0,writable:!0,value:i}):e[n]=i)(e,"symbol"!=typeof n?n+"":n,i);Object.defineProperties(exports,{t:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const n=require("react/jsx-runtime"),i=require("react");let s;const r=new Uint8Array(16);function o(){if(!s&&(s="undefined"!=typeof crypto&&crypto.getRandomValues&&crypto.getRandomValues.bind(crypto),!s))throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");return s(r)}const a=[];for(let S=0;S<256;++S)a.push((S+256).toString(16).slice(1));const c={randomUUID:"undefined"!=typeof crypto&&crypto.randomUUID&&crypto.randomUUID.bind(crypto)};function d(t,e,n){if(c.randomUUID&&!t)return c.randomUUID();const i=(t=t||{}).random||(t.rng||o)();return i[6]=15&i[6]|64,i[8]=63&i[8]|128,function(t,e=0){return a[t[e+0]]+a[t[e+1]]+a[t[e+2]]+a[t[e+3]]+"-"+a[t[e+4]]+a[t[e+5]]+"-"+a[t[e+6]]+a[t[e+7]]+"-"+a[t[e+8]]+a[t[e+9]]+"-"+a[t[e+10]]+a[t[e+11]]+a[t[e+12]]+a[t[e+13]]+a[t[e+14]]+a[t[e+15]]}(i)}const h=t=>{let e=2166136261;const n=t.length;for(let i=0;i<n;i++)e^=t.charCodeAt(i),e+=(e<<1)+(e<<4)+(e<<7)+(e<<8)+(e<<24);return("0000000"+(e>>>0).toString(16)).substr(-8)};class u{constructor(t="local"){e(this,"memoryStore",{}),e(this,"keyPrefix","engage_"),e(this,"domain"),this.type=t,this.domain=this.getCookieDomain()}getItem(t){const e=this.keyPrefix+t;if(this.memoryStore.hasOwnProperty(e))return this.memoryStore[e];try{if("local"===this.type&&this.isBrowser())return window.localStorage.getItem(e);if("cookie"===this.type&&this.isBrowser())return this.getCookie(e)}catch(n){return null}return null}setItem(t,e){const n=this.keyPrefix+t;this.memoryStore[n]=e;try{"local"===this.type&&this.isBrowser()?window.localStorage.setItem(n,e):"cookie"===this.type&&this.isBrowser()&&this.setCookie(n,e,365)}catch(i){this.isQuotaError(i)&&(this.type="memory")}}removeItem(t){const e=this.keyPrefix+t;delete this.memoryStore[e];try{"local"===this.type&&this.isBrowser()?window.localStorage.removeItem(e):"cookie"===this.type&&this.isBrowser()&&this.setCookie(e,"",-1)}catch(n){}}getCookie(t){const e=t+"=",n=document.cookie.split(";");for(let i=0;i<n.length;i++){let t=n[i];for(;" "===t.charAt(0);)t=t.substring(1,t.length);if(0===t.indexOf(e))return decodeURIComponent(t.substring(e.length,t.length))}return null}setCookie(t,e,n){let i="";if(n){const t=new Date;t.setTime(t.getTime()+24*n*60*60*1e3),i="; expires="+t.toUTCString()}document.cookie=`${t}=${encodeURIComponent(e)}${i}; path=/; domain=${this.domain}; SameSite=Lax; Secure`}getCookieDomain(){if(!this.isBrowser())return"";const t=window.location.hostname,e=t.split(".");return 1===e.length||"localhost"===t?"":e.length>2?"."+e.slice(-2).join("."):"."+t}isBrowser(){try{return"undefined"!=typeof window&&void 0!==window.document}catch(t){return!1}}isQuotaError(t){return t instanceof DOMException&&(22===t.code||1014===t.code||"QuotaExceededError"===t.name||"NS_ERROR_DOM_QUOTA_REACHED"===t.name)}}class l{constructor(t){e(this,"storage"),e(this,"SESSION_TIMEOUT",18e5),e(this,"deviceId"),e(this,"sessionId"),e(this,"userId",null),e(this,"currentUrl"),e(this,"referrer"),this.storage=new u(t.persistence),this.deviceId=this.getOrSetDeviceId(),this.sessionId="",this.manageSession(),"undefined"!=typeof window?(this.currentUrl=window.location.href,this.referrer=document.referrer,this.listenToHistory()):(this.currentUrl="",this.referrer="")}getOrSetDeviceId(){const t=this.storage.getItem("device_id");if(t)return t;const e=(()=>{if("undefined"==typeof window)return"server-side-id";const t=navigator,e=window.screen,n={userAgent:t.userAgent||"",screenRes:`${e.width}x${e.height}`,colorDepth:e.colorDepth||0,timezone:(new Date).getTimezoneOffset(),language:t.language||"en-US",platform:t.platform||"unknown",hardwareConcurrency:t.hardwareConcurrency||1,deviceMemory:t.deviceMemory||0},i=[n.platform,n.language,n.screenRes,n.colorDepth,n.timezone,n.hardwareConcurrency,n.deviceMemory].join("|");return`${h(i)}-${h(n.userAgent)}`})();return this.storage.setItem("device_id",e),e}manageSession(){const t=Date.now(),e=this.storage.getItem("session_id"),n=parseInt(this.storage.getItem("last_activity")||"0");if(!e||t-n>this.SESSION_TIMEOUT?(this.sessionId=`sess_${t}_${Math.random().toString(36).substr(2,9)}`,this.storage.setItem("session_id",this.sessionId)):this.sessionId=e,this.storage.setItem("last_activity",t.toString()),"undefined"!=typeof window){const t=()=>this.storage.setItem("last_activity",Date.now().toString());window.addEventListener("click",t),window.addEventListener("scroll",t)}}listenToHistory(){const t=history.pushState;history.pushState=(...e)=>{t.apply(history,e),this.handleUrlChange()},window.addEventListener("popstate",()=>this.handleUrlChange())}handleUrlChange(){const t=window.location.href;t!==this.currentUrl&&(this.referrer=this.currentUrl,this.currentUrl=t)}getPayload(){var t;return{library:{name:"@engagepro/analytics",version:"2.0.0"},user:{anonymousId:this.deviceId,id:this.userId},session:{id:this.sessionId,startTime:parseInt(this.sessionId.split("_")[1]||Date.now().toString())},page:{path:"undefined"!=typeof window?window.location.pathname:"",referrer:this.referrer,title:"undefined"!=typeof document?document.title:"",search:"undefined"!=typeof window?window.location.search:"",url:this.currentUrl},network:{online:"undefined"==typeof navigator||navigator.onLine,downlink:null==(t=navigator.connection)?void 0:t.downlink},screen:{width:"undefined"!=typeof screen?screen.width:0,height:"undefined"!=typeof screen?screen.height:0,density:"undefined"!=typeof window?window.devicePixelRatio:1},device:{fingerprint:this.deviceId,type:this.getDeviceType(),userAgent:"undefined"!=typeof navigator?navigator.userAgent:"server"},locale:"undefined"!=typeof navigator?navigator.language:"en-US",timezone:Intl.DateTimeFormat().resolvedOptions().timeZone}}getDeviceType(){if("undefined"==typeof navigator)return"desktop";const t=navigator.userAgent;return/(tablet|ipad|playbook|silk)|(android(?!.*mobi))/i.test(t)?"tablet":/Mobile|Android|iP(hone|od)|IEMobile|BlackBerry|Kindle|Silk-Accelerated/.test(t)?"mobile":"desktop"}}class f{constructor(t){e(this,"queue",[]),e(this,"storage"),e(this,"transport"),e(this,"STORAGE_KEY","engage_queue_v1"),e(this,"isFlushing",!1),e(this,"flushInterval"),e(this,"retryCount",0),this.transport=t,this.storage=new u("local"),this.load(),"undefined"!=typeof window&&(window.addEventListener("online",()=>{this.retryCount=0,this.flush()}),window.addEventListener("visibilitychange",()=>{"hidden"===document.visibilityState&&this.flush()})),this.startTimer()}startTimer(){this.flushInterval&&clearInterval(this.flushInterval);const t=3e3*Math.pow(2,this.retryCount);this.flushInterval=setInterval(()=>{this.flush()},Math.min(t,3e4))}enqueue(t){this.queue.push(t),this.save(),(this.queue.length>=10||"PURCHASE"===t.standardEvent)&&this.flush()}save(){this.storage.setItem(this.STORAGE_KEY,JSON.stringify(this.queue))}load(){const t=this.storage.getItem(this.STORAGE_KEY);if(t)try{this.queue=JSON.parse(t)}catch(e){this.queue=[]}}async flush(){if(0===this.queue.length||this.isFlushing)return;if("undefined"!=typeof navigator&&!navigator.onLine)return;this.isFlushing=!0;const t=[...this.queue];this.queue=[],this.save();try{if(!(await this.transport.send(t)))throw new Error("Server rejected batch");this.retryCount=0,this.startTimer()}catch(e){this.queue=[...t,...this.queue],this.save(),this.retryCount++,this.startTimer()}finally{this.isFlushing=!1}}}class p{constructor(t){this.apiEndpoint=t}async send(t){const e=JSON.stringify({batch:t,sentAt:(new Date).toISOString()});if("undefined"!=typeof navigator&&navigator.sendBeacon&&e.length<6e4){const t=new Blob([e],{type:"application/json"});if(navigator.sendBeacon(this.apiEndpoint,t))return!0}try{return(await fetch(this.apiEndpoint,{method:"POST",headers:{"Content-Type":"application/json"},body:e,keepalive:!0})).ok}catch(n){return!1}}}const w="https://engage-api.bluenath.com/api/v1/tracking/ingest",y=new Set(["localhost","127.0.0.1"]),v={$:"USD",US$:"USD",USD:"USD","₹":"INR",RS:"INR","RS.":"INR",INR:"INR","€":"EUR",EUR:"EUR","£":"GBP",GBP:"GBP","¥":"JPY",JPY:"JPY"},m=t=>{if("string"!=typeof t)return;const e=t.trim().toUpperCase();return e?v[e]?v[e]:e.includes("₹")||e.startsWith("RS")?"INR":e.includes("$")&&!e.includes("CAD")?"USD":e.includes("€")?"EUR":e.includes("£")?"GBP":e.includes("¥")?"JPY":/^[A-Z]{3}$/.test(e)?e:void 0:void 0};class g{constructor(t){e(this,"config"),e(this,"context"),e(this,"queue"),e(this,"transport"),e(this,"identify",(t,e)=>{this.context.userId=t,this.processEvent({event:"Identify",properties:{traits:e},standardEvent:"LOGIN",intent:"identity",confidence:1})}),e(this,"page",(t,e)=>{const n=this.context.getPayload().page;this.processEvent({event:t||n.title||"Unknown Page",properties:{path:n.path,referrer:n.referrer,title:n.title,...e},standardEvent:"PAGE_VIEW",intent:"navigation",confidence:1})}),e(this,"track",(t,e,n)=>{this.processEvent({event:t,properties:e||{},...n})}),e(this,"trackRevenue",(t,e,n)=>{const i=Math.max(0,(t=>{if("number"==typeof t)return Number.isFinite(t)?t:0;const e=t.trim().replace(/[^0-9.+-]/g,""),n=Number(e);return Number.isFinite(n)?n:0})(t)),s=m(null==e?void 0:e.currency)||m(null==e?void 0:e.currencyCode)||m(null==e?void 0:e.currencySymbol)||("string"==typeof t?m(t):void 0)||"USD";this.track("PURCHASE",{...e||{},value:i,amount:i,valuePaise:Math.round(100*i),amountPaise:Math.round(100*i),currency:s,currencyCode:s},{standardEvent:"PURCHASE",intent:"commerce",confidence:1,...n})}),this.config=t,this.transport=new p((t=>{if(!t)return w;try{const e=new URL(t);return e.hostname.endsWith("bluenath.com")||y.has(e.hostname)?(e.pathname="/api/v1/tracking/ingest",e.search="",e.hash="",e.toString()):w}catch{return w}})(t.apiHost)),this.context=new l({persistence:t.tracking.useCookies?"cookie":"local"}),this.queue=new f(this.transport)}parseRef(t){if(!t)return{};const e=t.match(/^camp_([^_]+)_cr_([^_]+)$/);return e?{campaignId:e[1],creatorId:e[2]}:{}}processEvent(t){const e=this.context.getPayload(),n=t.properties.ref,i=("string"==typeof n?n:void 0)||new URLSearchParams(e.page.search||"").get("ref")||void 0,s=this.parseRef(i),r=t.properties.value??t.properties.amount??t.properties.valuePaise??t.properties.amountPaise,o=Number(r),a=t.properties.campaignId,c=t.properties.creatorId,h=t.properties.currency,u={event:t.event,properties:t.properties,standardEvent:t.standardEvent,intent:t.intent,confidence:t.confidence,rawLabel:t.rawLabel,timestamp:(new Date).toISOString(),messageId:d(),writeKey:this.config.writeKey,ref:i,campaignId:("string"==typeof a?a:void 0)||s.campaignId,creatorId:("string"==typeof c?c:void 0)||s.creatorId,value:Number.isFinite(o)?Math.round(o):void 0,valuePaise:Number.isFinite(o)?Math.round(100*o):void 0,currency:("string"==typeof h?h:void 0)||"USD",userId:e.user.id||void 0,anonymousId:e.user.anonymousId,context:e};this.config.debug,this.queue.enqueue(u)}}class b{constructor(t){e(this,"analytics"),e(this,"metrics",{}),this.analytics=t,"undefined"!=typeof window&&"PerformanceObserver"in window&&this.observe()}observe(){try{new PerformanceObserver(t=>{for(const e of t.getEntries()){const t=e;t.hadRecentInput||(this.metrics.cls=(this.metrics.cls||0)+t.value)}}).observe({type:"layout-shift",buffered:!0}),new PerformanceObserver(t=>{const e=t.getEntries(),n=e[e.length-1];this.metrics.lcp=n.renderTime||n.loadTime,this.logMetric("LCP",this.metrics.lcp)}).observe({type:"largest-contentful-paint",buffered:!0}),new PerformanceObserver(t=>{const e=t.getEntries()[0];e&&(this.metrics.fid=e.processingStart-e.startTime,this.logMetric("FID",this.metrics.fid))}).observe({type:"first-input",buffered:!0}),window.addEventListener("visibilitychange",()=>{"hidden"===document.visibilityState&&this.metrics.cls&&this.logMetric("CLS",this.metrics.cls)})}catch(t){}}logMetric(t,e){e<0||this.analytics.track(`Core Web Vital: ${t}`,{metric:t,value:Math.round(e)},{standardEvent:"PERFORMANCE",intent:"performance",confidence:1,rawLabel:`${t}: ${Math.round(e)}ms`})}}const E=i.createContext(null);let R=null;exports.EngageProProvider=({children:t,...e})=>{const s=i.useRef(null),r=i.useRef(null);s.current||(s.current=new g(e),"undefined"!=typeof window&&new b(s.current));const o=s.current;return i.useEffect(()=>{if(!e.tracking.autoTrack)return;const t=t=>{const e=t.target.closest('button, a, input[type="submit"], [data-track], .clickable');if(e){const t=Date.now(),n=r.current;n&&n.el===e&&t-n.ts<500?(n.count++,n.ts=t,3===n.count&&(o.track("Rage Click detected",{element:e.tagName},{standardEvent:"RAGE_CLICK",intent:"frustration",confidence:1}),r.current=null)):r.current={el:e,count:1,ts:t};const i=(t=>{let e=(t.innerText||t.value||t.getAttribute("aria-label")||"").trim();if(!e){const n=t.querySelector("img");n&&n.alt&&(e=n.alt);const i=t.querySelector("title");i&&(e=i.textContent||"")}const n=e.slice(0,100),i=n.toLowerCase(),s=(t.id||"").toLowerCase(),r=t.href||"";return/add to (cart|bag)|buy now/.test(i)||s.includes("add-to-cart")?{standard:"ADD_TO_CART",intent:"commerce",label:n,confidence:.9}:/checkout|proceed/.test(i)||r.includes("/checkout")?{standard:"INITIATE_CHECKOUT",intent:"commerce",label:n,confidence:.9}:/place order|pay now/.test(i)||s.includes("place-order")?{standard:"PURCHASE",intent:"commerce",label:n,confidence:.95}:/cancel order/.test(i)||s.includes("cancel")?{standard:"ORDER_CANCEL",intent:"lifecycle",label:n,confidence:.85}:/refund|return/.test(i)||s.includes("refund")?{standard:"ORDER_REFUND",intent:"lifecycle",label:n,confidence:.85}:/track package|shipping/.test(i)?{standard:"TRACK_PACKAGE",intent:"lifecycle",label:n,confidence:.8}:/write review/.test(i)||i.includes("star")&&/^[1-5]/.test(i)?{standard:"RATE_PRODUCT",intent:"engagement",label:n,confidence:.8}:i.includes("search")||s.includes("search")?{standard:"SEARCH",intent:"search",label:n,confidence:.7}:{standard:"GENERIC",intent:"interaction",label:n,confidence:.5}})(e),s="A"===e.tagName;o.track("Interaction",{element:e.tagName.toLowerCase(),id:e.id,destination:s?e.href:void 0},{standardEvent:i.standard,intent:i.intent,rawLabel:i.label,confidence:i.confidence})}},n=t=>{const e=t.target;(t=>"password"===t.getAttribute("type")||"hidden"===t.getAttribute("type")||/password|cvc|card|cc-num|ssn|credit|hidden/i.test(t.getAttribute("name")||t.id||""))(e)||"focusin"!==t.type||e.dataset.tracked||(e.dataset.tracked="true",o.track("Form Start",{field:e.name||e.id},{standardEvent:"FORM_START",intent:"identity"}))},i=()=>{const t=new URLSearchParams(window.location.search);t.has("q")&&o.track("Search Query",{query:t.get("q")},{standardEvent:"SEARCH",intent:"search"}),requestAnimationFrame(()=>o.page())},s=history.pushState;return history.pushState=(...t)=>{s.apply(history,t),i()},window.addEventListener("popstate",i),window.addEventListener("click",t,!0),window.addEventListener("focusin",n,!0),i(),()=>{history.pushState=s,window.removeEventListener("popstate",i),window.removeEventListener("click",t,!0),window.removeEventListener("focusin",n,!0)}},[e.tracking.autoTrack]),n.jsx(E.Provider,{value:o,children:t})},exports.default=g,exports.init=t=>(R||(R=new g(t)),R),exports.useAnalytics=()=>{const t=i.useContext(E);if(!t)throw new Error("useAnalytics must be used within EngageProProvider");return t};
|
package/dist/index.js
CHANGED
|
@@ -408,6 +408,22 @@ class Transport {
|
|
|
408
408
|
const DEFAULT_INGEST_ENDPOINT = "https://engage-api.bluenath.com/api/v1/tracking/ingest";
|
|
409
409
|
const FIXED_INGEST_PATH = "/api/v1/tracking/ingest";
|
|
410
410
|
const ALLOWED_DEV_HOSTS = /* @__PURE__ */ new Set(["localhost", "127.0.0.1"]);
|
|
411
|
+
const DEFAULT_CURRENCY = "USD";
|
|
412
|
+
const SYMBOL_TO_CURRENCY = {
|
|
413
|
+
$: "USD",
|
|
414
|
+
US$: "USD",
|
|
415
|
+
USD: "USD",
|
|
416
|
+
"₹": "INR",
|
|
417
|
+
RS: "INR",
|
|
418
|
+
"RS.": "INR",
|
|
419
|
+
INR: "INR",
|
|
420
|
+
"€": "EUR",
|
|
421
|
+
EUR: "EUR",
|
|
422
|
+
"£": "GBP",
|
|
423
|
+
GBP: "GBP",
|
|
424
|
+
"¥": "JPY",
|
|
425
|
+
JPY: "JPY"
|
|
426
|
+
};
|
|
411
427
|
const resolveIngestEndpoint = (apiHost) => {
|
|
412
428
|
if (!apiHost) return DEFAULT_INGEST_ENDPOINT;
|
|
413
429
|
try {
|
|
@@ -427,6 +443,25 @@ const resolveIngestEndpoint = (apiHost) => {
|
|
|
427
443
|
return DEFAULT_INGEST_ENDPOINT;
|
|
428
444
|
}
|
|
429
445
|
};
|
|
446
|
+
const parseCurrencyToken = (value) => {
|
|
447
|
+
if (typeof value !== "string") return void 0;
|
|
448
|
+
const trimmed = value.trim().toUpperCase();
|
|
449
|
+
if (!trimmed) return void 0;
|
|
450
|
+
if (SYMBOL_TO_CURRENCY[trimmed]) return SYMBOL_TO_CURRENCY[trimmed];
|
|
451
|
+
if (trimmed.includes("₹") || trimmed.startsWith("RS")) return "INR";
|
|
452
|
+
if (trimmed.includes("$") && !trimmed.includes("CAD")) return "USD";
|
|
453
|
+
if (trimmed.includes("€")) return "EUR";
|
|
454
|
+
if (trimmed.includes("£")) return "GBP";
|
|
455
|
+
if (trimmed.includes("¥")) return "JPY";
|
|
456
|
+
return /^[A-Z]{3}$/.test(trimmed) ? trimmed : void 0;
|
|
457
|
+
};
|
|
458
|
+
const parseRevenueAmount = (value) => {
|
|
459
|
+
if (typeof value === "number") return Number.isFinite(value) ? value : 0;
|
|
460
|
+
const normalized = value.trim();
|
|
461
|
+
const numeric = normalized.replace(/[^0-9.+-]/g, "");
|
|
462
|
+
const parsed = Number(numeric);
|
|
463
|
+
return Number.isFinite(parsed) ? parsed : 0;
|
|
464
|
+
};
|
|
430
465
|
class EngagePro {
|
|
431
466
|
constructor(config) {
|
|
432
467
|
__publicField(this, "config");
|
|
@@ -469,13 +504,19 @@ class EngagePro {
|
|
|
469
504
|
...intelligence
|
|
470
505
|
});
|
|
471
506
|
});
|
|
472
|
-
__publicField(this, "trackRevenue", (
|
|
507
|
+
__publicField(this, "trackRevenue", (amount, properties, intelligence) => {
|
|
508
|
+
const parsedAmount = Math.max(0, parseRevenueAmount(amount));
|
|
509
|
+
const currency = parseCurrencyToken(properties == null ? void 0 : properties.currency) || parseCurrencyToken(properties == null ? void 0 : properties.currencyCode) || parseCurrencyToken(properties == null ? void 0 : properties.currencySymbol) || (typeof amount === "string" ? parseCurrencyToken(amount) : void 0) || DEFAULT_CURRENCY;
|
|
473
510
|
this.track(
|
|
474
511
|
"PURCHASE",
|
|
475
512
|
{
|
|
476
513
|
...properties || {},
|
|
477
|
-
value:
|
|
478
|
-
|
|
514
|
+
value: parsedAmount,
|
|
515
|
+
amount: parsedAmount,
|
|
516
|
+
valuePaise: Math.round(parsedAmount * 100),
|
|
517
|
+
amountPaise: Math.round(parsedAmount * 100),
|
|
518
|
+
currency,
|
|
519
|
+
currencyCode: currency
|
|
479
520
|
},
|
|
480
521
|
{
|
|
481
522
|
standardEvent: "PURCHASE",
|
|
@@ -504,7 +545,7 @@ class EngagePro {
|
|
|
504
545
|
const refValue = data.properties.ref;
|
|
505
546
|
const ref = (typeof refValue === "string" ? refValue : void 0) || new URLSearchParams(baseContext.page.search || "").get("ref") || void 0;
|
|
506
547
|
const refParts = this.parseRef(ref);
|
|
507
|
-
const valueCandidate = data.properties.
|
|
548
|
+
const valueCandidate = data.properties.value ?? data.properties.amount ?? data.properties.valuePaise ?? data.properties.amountPaise;
|
|
508
549
|
const value = Number(valueCandidate);
|
|
509
550
|
const campaignIdValue = data.properties.campaignId;
|
|
510
551
|
const creatorIdValue = data.properties.creatorId;
|
|
@@ -525,8 +566,8 @@ class EngagePro {
|
|
|
525
566
|
campaignId: (typeof campaignIdValue === "string" ? campaignIdValue : void 0) || refParts.campaignId,
|
|
526
567
|
creatorId: (typeof creatorIdValue === "string" ? creatorIdValue : void 0) || refParts.creatorId,
|
|
527
568
|
value: Number.isFinite(value) ? Math.round(value) : void 0,
|
|
528
|
-
valuePaise: Number.isFinite(value) ? Math.round(value) : void 0,
|
|
529
|
-
currency: (typeof currencyValue === "string" ? currencyValue : void 0) ||
|
|
569
|
+
valuePaise: Number.isFinite(value) ? Math.round(value * 100) : void 0,
|
|
570
|
+
currency: (typeof currencyValue === "string" ? currencyValue : void 0) || DEFAULT_CURRENCY,
|
|
530
571
|
// Identity
|
|
531
572
|
userId: baseContext.user.id || void 0,
|
|
532
573
|
anonymousId: baseContext.user.anonymousId,
|
package/dist/types/index.d.ts
CHANGED
|
@@ -53,8 +53,13 @@ export interface AnalyticsEvent {
|
|
|
53
53
|
creatorId?: string;
|
|
54
54
|
ref?: string;
|
|
55
55
|
value?: number;
|
|
56
|
+
amount?: number;
|
|
56
57
|
valuePaise?: number;
|
|
58
|
+
amountPaise?: number;
|
|
57
59
|
currency?: string;
|
|
60
|
+
currencyCode?: string;
|
|
61
|
+
currencySymbol?: string;
|
|
62
|
+
baseCurrency?: string;
|
|
58
63
|
context?: Partial<AnalyticsContext>;
|
|
59
64
|
}
|
|
60
65
|
export interface EngageConfig {
|