@carter-rmn/cpix-js 1.0.6 → 1.0.8

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.
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Bot detection utility to identify automated browsers and bots
3
+ */
4
+ export default class BotDetection {
5
+ /**
6
+ * Known bot user agent patterns
7
+ */
8
+ private static readonly BOT_USER_AGENTS;
9
+ /**
10
+ * Checks if the current browser is a bot or automated browser
11
+ * @returns true if bot is detected, false otherwise
12
+ */
13
+ static isBot(): boolean;
14
+ /**
15
+ * Checks for missing browser features that indicate automation
16
+ * This is a conservative check to avoid false positives
17
+ */
18
+ private static hasMissingBrowserFeatures;
19
+ /**
20
+ * Checks for headless browser indicators
21
+ */
22
+ private static isHeadlessBrowser;
23
+ }
@@ -2,6 +2,13 @@ import { DeviceNetworkParameters } from '../types/common.types';
2
2
 
3
3
  export default class Browser {
4
4
  static getBrowserInfo(): string;
5
+ static getBrowserName(): string;
6
+ static getBrowserVersion(): string;
7
+ static getScreenResolution(): string;
8
+ static getViewportSize(): string;
9
+ static getLanguage(): string;
10
+ static getOSVersion(): string;
11
+ static getUserAgent(): string;
5
12
  static getDeviceCategory(): string;
6
13
  static getDevicePlatform(): string;
7
14
  static getDeviceManufacturer(): string;
@@ -7,5 +7,5 @@ export default class Cookie {
7
7
  static exists(name: string): boolean;
8
8
  static setUtms(): void;
9
9
  static getUtms(): any;
10
- static createSession(): void;
10
+ static createSession(regenerate?: boolean): void;
11
11
  }
package/dist/cpix.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";var y=Object.defineProperty;var S=(l,e,t)=>e in l?y(l,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):l[e]=t;var o=(l,e,t)=>(S(l,typeof e!="symbol"?e+"":e,t),t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const v="@carter-rmn/cpix-js",P="1.0.5",_="module",x=["dist"],A="dist/cpix.umd.cjs",b="dist/cpix.js",T="dist/cpix.d.ts",R={".":{import:"./dist/cpix.js",require:"./dist/cpix.umd.cjs"}},I={dev:"vite",build:"tsc && vite build",preview:"vite preview"},U={picocolors:"^1.0.0","rollup-plugin-visualizer":"^5.12.0",typescript:"^5.2.2",vite:"^5.2.0","vite-plugin-progress":"^0.0.7"},C={"vite-plugin-dts":"^3.8.1"},m={name:v,version:P,type:_,files:x,main:A,module:b,types:T,exports:R,scripts:I,devDependencies:U,dependencies:C},n={DEBUG:!1,TRACKER_FUNC_NAME:"cpix",API_URL:"",QUEUE_MAX_RETRIES:3,QUEUE_INITIAL_DELAY:1e4,version:m.version,package:m.name,USER_PROPERTIES:{},SESSION_EXPIRY_DAYS:14,COMMON_PROPERTIES:{}},c={SESSION:"cpix_session",META_PARAMETERS:"cpix_meta_parameters",ACCESS_TOKEN:"cpix_access_token",UTM:"cpix_utm"},O=["utm_source","utm_medium","utm_term","utm_content","utm_campaign"],u=function(){const l=()=>n.DEBUG;return{info:function(...e){console.log(...e)},debug:function(...e){l()&&console.log(...e)},error:function(...e){console.error(...e)}}}();class D extends EventTarget{constructor(t={maxRetries:3,initialDelay:1e4,consumerHandler:i=>(u.debug("Consuming event:",i),Promise.resolve())}){super();o(this,"dataQueue");o(this,"retryQueue");o(this,"maxRetries");o(this,"initialDelay");o(this,"publishEvent");o(this,"retryEvent");o(this,"handler");this.dataQueue=[],this.retryQueue=[],this.maxRetries=t.maxRetries,this.initialDelay=t.initialDelay,this.handler=t.consumerHandler,this.publishEvent=new Event("eventPublished"),this.retryEvent=new Event("retryMessage"),this.consume(),this.retry()}publish(t){u.debug("publishing event");const i={data:t,id:`${Date.now()+Math.random()}`,retryCount:0,retryDelay:this.initialDelay};this.dataQueue.push(i),this.dispatchEvent(this.publishEvent)}consume(){u.debug("Started Consumer Queue"),this.addEventListener("eventPublished",async()=>{for(;this.dataQueue.length>0;){const t=this.dataQueue.shift(),{data:i={}}=t;try{await this.handler(i),this.acknowledge(t==null?void 0:t.id)}catch(r){u.error("Failed to publish event:",r),this.scheduleRetry(t)}}})}scheduleRetry(t){if(t.retryCount>=this.maxRetries){u.error("Max retries reached for message:",t);return}setTimeout(()=>{this.retryQueue.push({...t,retryCount:t.retryCount+1,retryDelay:t.retryDelay*2}),this.dispatchEvent(this.retryEvent)},t.retryDelay)}acknowledge(t){this.dataQueue=this.dataQueue.filter(i=>i.id!==t)}retry(){u.debug("Started Retry Queue"),this.addEventListener("retryMessage",async()=>{for(;this.retryQueue.length>0;){const t=this.retryQueue.shift(),{data:i={}}=t;try{await this.handler(i),this.acknowledge(t==null?void 0:t.id)}catch(r){u.error("Failed to publish event:",r),this.scheduleRetry(t)}}})}}class d{static getBrowserInfo(){var r,a,p,f,g;const e=navigator.userAgent||"";let t,i;return/chrome/i.test(e)?(t="Chrome",i=(r=e.match(/chrome\/(\d+)/i))==null?void 0:r[1]):/firefox/i.test(e)?(t="Firefox",i=(a=e.match(/firefox\/(\d+)/i))==null?void 0:a[1]):/safari/i.test(e)?(t="Safari",i=(p=e.match(/version\/(\d+)/i))==null?void 0:p[1]):/edge/i.test(e)?(t="Edge",i=(f=e.match(/edge\/(\d+)/i))==null?void 0:f[1]):/trident/i.test(e)?(t="Internet Explorer",i=(g=e.match(/rv:(\d+)/i))==null?void 0:g[1]):(t="Unknown",i="Unknown"),`${t} ${i}`}static getDeviceCategory(){const e=navigator.userAgent;return/mobile/i.test(e)?"Mobile":/tablet/i.test(e)?"Tablet":"Desktop"}static getDevicePlatform(){const e=navigator.userAgent;return/android/i.test(e)?"Android":/iphone|ipad|ipod/i.test(e)?"iOS":/windows phone/i.test(e)?"Windows Phone":/mac|Macintosh/i.test(e)?"Mac":/windows|Microsoft/i.test(e)?"Windows":/linux/i.test(e)?"Linux":"Unknown"}static getDeviceManufacturer(){const e=navigator.userAgent;let t;return/iphone|ipad|ipod|mac|Macintosh/i.test(e)?t="Apple":/samsung/i.test(e)?t="Samsung":/google/i.test(e)?t="Google":/huawei/i.test(e)?t="Huawei":/xiaomi/i.test(e)?t="Xiaomi":/oneplus/i.test(e)?t="OnePlus":/dell/i.test(e)?t="Dell":/lenovo/i.test(e)?t="Lenovo":/acer/i.test(e)?t="Acer":/asus/i.test(e)?t="Asus":/toshiba/i.test(e)?t="Toshiba":t="Unknown",t}static async getDeviceNetworkParameters(){try{const e=await fetch(`${n.API_URL}/api/geolocation`),{data:t}=await e.json();return{city:t.city||"Unknown",region:t.region||"Unknown",country:t.country||"Unknown",timezone:t.timezone||"Unknown",loc:t.loc||"Unknown",ip_address:t.ip_address||"Unknown"}}catch(e){return u.error("Error retrieving device network parameters:",e),{city:"Unknown",region:"Unknown",country:"Unknown",timezone:"Unknown",loc:"Unknown",ip_address:"Unknown"}}}static async aquireAccessToken(e){try{return(await(await fetch(`${n.API_URL}/api/authenticate`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({accountId:e,metadata:{sdk:n.package,version:n.version,hostname:window.location.hostname}})})).json()).accessToken}catch(t){throw u.error("Error acquiring access token:",t),new Error("[CPIX] Authentication error")}}}class h{static isPresent(e){return typeof e<"u"&&e!==null&&e!==""}static now(){return 1*new Date().getTime()}static guid(){return m.version+"-xxxxxxxx-".replace(/[x]/g,function(e){const t=Math.random()*36|0;return(e=="x"?t:t&3|8).toString(36)})+(1*new Date().getTime()).toString(36)}static optionalData(e){return h.isPresent(e)===!1?"":typeof e=="object"?h.optionalData(JSON.stringify(e)):typeof e=="function"?h.optionalData(e()):String(e)}static sleep(e){return new Promise(t=>setTimeout(t,e))}}class E{static getParametersByName(e,t){t||(t=window.location.href),e=e.replace(/[[\]]/g,"\\$&");const i=new RegExp("[?&]"+e+"(=([^&#]*)|&|#|$)","gi"),r=[];let a;for(;(a=i.exec(t))!==null;)a[2]&&r.push(decodeURIComponent(a[2].replace(/\+/g," ")));return r.length>0?r:null}static externalHost(e){var t;return e.hostname!=location.hostname&&((t=e==null?void 0:e.protocol)==null?void 0:t.indexOf("http"))===0}}class s{static prefix(){return`__${n.TRACKER_FUNC_NAME}__`}static get(e){const t=`${s.prefix()}${e}`,i=document.cookie.split("; ").find(r=>r.startsWith(`${t}=`));return i?i.split("=")[1]:void 0}static set(e,t,i){const r=`${s.prefix()}${e}`,a=new Date;a.setTime(a.getTime()+i*60*1e3),document.cookie=`${r}=${t}; expires=${a.toUTCString()}; path=/`}static delete(e){const t=`${s.prefix()}${e}`;document.cookie=`${t}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/`}static clear(){document.cookie.split("; ").filter(e=>e.startsWith(s.prefix())).forEach(e=>{const t=e.split("=")[0];document.cookie=`${t}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/`})}static exists(e){return!!s.get(e)}static setUtms(){const e=O;let t=!1;for(let i=0;i<e.length;i++){const r=e[i];if(h.isPresent(E.getParametersByName(r,window.location.href))){t=!0;break}}if(t){let i;const r=[];for(let a=0;a<e.length;a++){const p=e[a];i=E.getParametersByName(p,window.location.href),r.push({[p]:encodeURIComponent(i)})}s.set(c.UTM,JSON.stringify(r),n.SESSION_EXPIRY_DAYS*24*60)}}static getUtms(){const e=s.get(c.UTM);return h.isPresent(e)?JSON.parse(e):{}}static createSession(){s.exists(c.SESSION)||s.set(c.SESSION,h.guid(),n.SESSION_EXPIRY_DAYS*24*60),s.setUtms()}}class N{constructor(){o(this,"instances",[]);o(this,"initialized",!1);o(this,"sessionCreated",!1);o(this,"accessToken","");o(this,"metaParameters",{});o(this,"queue");if(!window)throw new Error("[CPIX] CarterAnalytics SDK can only be used in a browser environment");this.queue=new D({maxRetries:n.QUEUE_MAX_RETRIES,initialDelay:n.QUEUE_INITIAL_DELAY,consumerHandler:this.publishEventToServer.bind(this)})}async initialize(e){if(!e||e.length===0)throw new Error("[CPIX] At least one instance configuration is required for initialization");if(this.instances=e,n.DEBUG=this.instances[0].options.debug===!0,n.API_URL=this.instances[0].options.tracker_server_url,n.USER_PROPERTIES=this.instances[0].options.user_properties||{},n.SESSION_EXPIRY_DAYS=this.instances[0].options.session_expiry_days||14,n.COMMON_PROPERTIES=this.instances[0].options.common_properties||{},s.exists(c.SESSION)||(s.createSession(),this.sessionCreated=!0),s.exists(c.META_PARAMETERS)||await this.generateMetaParameters().then(t=>{this.metaParameters=t,s.set("metaParameters",JSON.stringify(t),60*24)}),s.setUtms(),this.metaParameters=JSON.parse(s.get("metaParameters")),this.initialized)throw new Error("[CPIX] CarterAnalytics SDK has already been initialized");if(!this.metaParameters)throw new Error("[CPIX] Meta parameters have not been generated");s.exists(c.ACCESS_TOKEN)||(this.accessToken=await d.aquireAccessToken(this.instances[0].client_id),s.set(c.ACCESS_TOKEN,this.accessToken,60*4)),this.initialized=!0,u.debug("CPIX Initialized"),u.debug("Carter Analytics SDK initialized with options:",this.instances),this.sessionCreated&&this.publishInit(),this.attachHistoryListener()}publishInit(){this.publish({event:"init",user_properties:n.USER_PROPERTIES,...this.metaParameters})}attachHistoryListener(){const e=history.pushState,t=history.replaceState,i=()=>{this.publish({event:"page_view",event_properties:{title:document.title,page:window.location.pathname,url:window.location.href},user_properties:n.USER_PROPERTIES,...this.metaParameters})};history.pushState=(...r)=>{e.apply(history,r),i()},history.replaceState=(...r)=>{t.apply(history,r),i()},window.addEventListener("popstate",i),i()}publish(e){if(!this.initialized)throw new Error("[CPIX] CarterAnalytics SDK has not been initialized. Please initialize before publishing events.");const t={...e,...this.metaParameters};t.utm_params=s.getUtms(),document.referrer&&(t.referrer=encodeURIComponent(document.referrer)),u.debug("Publishing event:",t),this.queue.publish(t),e.event==="logout"&&(s.delete(c.SESSION),s.delete(c.META_PARAMETERS),s.createSession(),this.generateMetaParameters().then(i=>{this.metaParameters=i,s.set(c.META_PARAMETERS,JSON.stringify(this.metaParameters),60*24),this.publishInit()}))}async generateMetaParameters(){if(!window)throw new Error("[CPIX] Meta parameters can only be generated in a browser environment");const e=await d.getDeviceNetworkParameters();return{client_id:this.instances[0].client_id,session:s.get(c.SESSION),location:{city:e.city,region:e.region,loc:e.loc,timezone:e.timezone,country:e.country},device:{category:d.getDeviceCategory(),brand:d.getDeviceManufacturer(),ip_address:e.ip_address,platform:d.getDevicePlatform(),cpix_sdk_version:n.version},referrer:encodeURIComponent(document.referrer)}}async publishEventToServer(e){try{e.timestamp=Date.now(),e.event_properties={url:window.location.href,...n.COMMON_PROPERTIES,...e.event_properties},e.device&&(e.device.cpix_sdk_version=n.version);const t=await fetch(`${n.API_URL}/api/event`,{method:"POST",body:JSON.stringify({event_data:e}),headers:{"Content-Type":"application/json",Authorization:`Bearer ${s.get(c.ACCESS_TOKEN)}`}});if(!t.ok)throw t.status===401&&(this.accessToken=await d.aquireAccessToken(this.instances[0].client_id),s.set(c.ACCESS_TOKEN,this.accessToken,60*4)),new Error("[CPIX] Failed to publish event");u.debug("Event published:",t.ok)}catch(t){throw u.error("Failed to publish event:",t),new Error("[CPIX] Failed to publish event")}}}const w=new N;typeof window<"u"&&(window.cpix=w);exports.CarterAnalytics=w;
1
+ "use strict";var v=Object.defineProperty;var y=(l,e,t)=>e in l?v(l,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):l[e]=t;var u=(l,e,t)=>(y(l,typeof e!="symbol"?e+"":e,t),t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const b="@carter-rmn/cpix-js",P="1.0.8",A="module",_=["dist"],U="dist/cpix.umd.cjs",T="dist/cpix.js",x="dist/cpix.d.ts",R={".":{import:"./dist/cpix.js",require:"./dist/cpix.umd.cjs"}},I={dev:"vite",build:"tsc && vite build",preview:"vite preview"},C={picocolors:"^1.0.0","rollup-plugin-visualizer":"^5.12.0",typescript:"^5.2.2",vite:"^5.2.0","vite-plugin-progress":"^0.0.7"},M={"vite-plugin-dts":"^3.8.1"},f={name:b,version:P,type:A,files:_,main:U,module:T,types:x,exports:R,scripts:I,devDependencies:C,dependencies:M},a={DEBUG:!1,TRACKER_FUNC_NAME:"cpix",API_URL:"",QUEUE_MAX_RETRIES:3,QUEUE_INITIAL_DELAY:1e4,version:f.version,package:f.name,USER_PROPERTIES:{},SESSION_EXPIRY_DAYS:14,COMMON_PROPERTIES:{}},o={SESSION:"cpix_session",META_PARAMETERS:"cpix_meta_parameters",ACCESS_TOKEN:"cpix_access_token",UTM:"cpix_utm"},k=["utm_source","utm_medium","utm_term","utm_content","utm_campaign"],n=function(){const l=()=>a.DEBUG;return{info:function(...e){console.log(...e)},debug:function(...e){l()&&console.log(...e)},error:function(...e){console.error(...e)}}}();class N extends EventTarget{constructor(t={maxRetries:3,initialDelay:1e4,consumerHandler:i=>(n.debug("Consuming event:",i),Promise.resolve())}){super();u(this,"dataQueue");u(this,"retryQueue");u(this,"maxRetries");u(this,"initialDelay");u(this,"publishEvent");u(this,"retryEvent");u(this,"handler");this.dataQueue=[],this.retryQueue=[],this.maxRetries=t.maxRetries,this.initialDelay=t.initialDelay,this.handler=t.consumerHandler,this.publishEvent=new Event("eventPublished"),this.retryEvent=new Event("retryMessage"),this.consume(),this.retry()}publish(t){n.debug("publishing event");const i={data:t,id:`${Date.now()+Math.random()}`,retryCount:0,retryDelay:this.initialDelay};this.dataQueue.push(i),this.dispatchEvent(this.publishEvent)}consume(){n.debug("Started Consumer Queue"),this.addEventListener("eventPublished",async()=>{for(;this.dataQueue.length>0;){const t=this.dataQueue.shift(),{data:i={}}=t;try{await this.handler(i),this.acknowledge(t==null?void 0:t.id)}catch(s){n.error("Failed to publish event:",s),this.scheduleRetry(t)}}})}scheduleRetry(t){if(t.retryCount>=this.maxRetries){n.error("Max retries reached for message:",t);return}setTimeout(()=>{this.retryQueue.push({...t,retryCount:t.retryCount+1,retryDelay:t.retryDelay*2}),this.dispatchEvent(this.retryEvent)},t.retryDelay)}acknowledge(t){this.dataQueue=this.dataQueue.filter(i=>i.id!==t)}retry(){n.debug("Started Retry Queue"),this.addEventListener("retryMessage",async()=>{for(;this.retryQueue.length>0;){const t=this.retryQueue.shift(),{data:i={}}=t;try{await this.handler(i),this.acknowledge(t==null?void 0:t.id)}catch(s){n.error("Failed to publish event:",s),this.scheduleRetry(t)}}})}}class d{static getBrowserInfo(){var s,c,h,p,w;const e=navigator.userAgent||"";let t,i;return/chrome/i.test(e)?(t="Chrome",i=(s=e.match(/chrome\/(\d+)/i))==null?void 0:s[1]):/firefox/i.test(e)?(t="Firefox",i=(c=e.match(/firefox\/(\d+)/i))==null?void 0:c[1]):/safari/i.test(e)?(t="Safari",i=(h=e.match(/version\/(\d+)/i))==null?void 0:h[1]):/edge/i.test(e)?(t="Edge",i=(p=e.match(/edge\/(\d+)/i))==null?void 0:p[1]):/trident/i.test(e)?(t="Internet Explorer",i=(w=e.match(/rv:(\d+)/i))==null?void 0:w[1]):(t="Unknown",i="Unknown"),`${t} ${i}`}static getBrowserName(){const e=navigator.userAgent||"";let t;return/chrome/i.test(e)&&!/edge/i.test(e)?t="Chrome":/firefox/i.test(e)?t="Firefox":/safari/i.test(e)&&!/chrome/i.test(e)?t="Safari":/edge/i.test(e)?t="Edge":/trident/i.test(e)?t="Internet Explorer":t="Unknown",t}static getBrowserVersion(){var i,s,c,h,p;const e=navigator.userAgent||"";let t;return/chrome/i.test(e)&&!/edge/i.test(e)?t=((i=e.match(/chrome\/(\d+)/i))==null?void 0:i[1])||"Unknown":/firefox/i.test(e)?t=((s=e.match(/firefox\/(\d+)/i))==null?void 0:s[1])||"Unknown":/safari/i.test(e)&&!/chrome/i.test(e)?t=((c=e.match(/version\/(\d+)/i))==null?void 0:c[1])||"Unknown":/edge/i.test(e)?t=((h=e.match(/edge\/(\d+)/i))==null?void 0:h[1])||"Unknown":/trident/i.test(e)?t=((p=e.match(/rv:(\d+)/i))==null?void 0:p[1])||"Unknown":t="Unknown",t}static getScreenResolution(){return typeof window>"u"||!window.screen?"Unknown":`${window.screen.width}x${window.screen.height}`}static getViewportSize(){return typeof window>"u"?"Unknown":`${window.innerWidth}x${window.innerHeight}`}static getLanguage(){var e;return typeof navigator>"u"?"Unknown":navigator.language||((e=navigator.languages)==null?void 0:e[0])||"Unknown"}static getOSVersion(){const e=navigator.userAgent||"";let t="Unknown";if(/iphone|ipad|ipod/i.test(e)){const i=e.match(/os (\d+[._]\d+)/i);i&&(t=i[1].replace("_","."))}else if(/android/i.test(e)){const i=e.match(/android (\d+(\.\d+)?)/i);i&&(t=i[1])}else if(/windows/i.test(e))if(/windows nt 10.0/i.test(e))t="10";else if(/windows nt 6.3/i.test(e))t="8.1";else if(/windows nt 6.2/i.test(e))t="8";else if(/windows nt 6.1/i.test(e))t="7";else{const i=e.match(/windows nt (\d+\.\d+)/i);i&&(t=i[1])}else if(/mac|Macintosh/i.test(e)){const i=e.match(/mac os x (\d+[._]\d+)/i);i&&(t=i[1].replace("_","."))}return t}static getUserAgent(){return typeof navigator>"u"||!navigator.userAgent?"Unknown":navigator.userAgent}static getDeviceCategory(){const e=navigator.userAgent;return/mobile/i.test(e)?"Mobile":/tablet/i.test(e)?"Tablet":"Desktop"}static getDevicePlatform(){const e=navigator.userAgent;return/android/i.test(e)?"Android":/iphone|ipad|ipod/i.test(e)?"iOS":/windows phone/i.test(e)?"Windows Phone":/mac|Macintosh/i.test(e)?"Mac":/windows|Microsoft/i.test(e)?"Windows":/linux/i.test(e)?"Linux":"Unknown"}static getDeviceManufacturer(){const e=navigator.userAgent;let t;return/iphone|ipad|ipod|mac|Macintosh/i.test(e)?t="Apple":/samsung/i.test(e)?t="Samsung":/google/i.test(e)?t="Google":/huawei/i.test(e)?t="Huawei":/xiaomi/i.test(e)?t="Xiaomi":/oneplus/i.test(e)?t="OnePlus":/dell/i.test(e)?t="Dell":/lenovo/i.test(e)?t="Lenovo":/acer/i.test(e)?t="Acer":/asus/i.test(e)?t="Asus":/toshiba/i.test(e)?t="Toshiba":t="Unknown",t}static async getDeviceNetworkParameters(){try{const e=await fetch(`${a.API_URL}/api/geolocation`),{data:t}=await e.json();return{city:t.city||"Unknown",region:t.region||"Unknown",country:t.country||"Unknown",timezone:t.timezone||"Unknown",loc:t.loc||"Unknown",ip_address:t.ip_address||"Unknown"}}catch(e){return n.error("Error retrieving device network parameters:",e),{city:"Unknown",region:"Unknown",country:"Unknown",timezone:"Unknown",loc:"Unknown",ip_address:"Unknown"}}}static async aquireAccessToken(e){try{return(await(await fetch(`${a.API_URL}/api/authenticate`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({accountId:e,metadata:{sdk:a.package,version:a.version,hostname:window.location.hostname}})})).json()).accessToken}catch(t){throw n.error("Error acquiring access token:",t),new Error("[CPIX] Authentication error")}}}class g{static isPresent(e){return typeof e<"u"&&e!==null&&e!==""}static now(){return 1*new Date().getTime()}static guid(){return f.version+"-xxxxxxxx-".replace(/[x]/g,function(e){const t=Math.random()*36|0;return(e=="x"?t:t&3|8).toString(36)})+(1*new Date().getTime()).toString(36)}static optionalData(e){return g.isPresent(e)===!1?"":typeof e=="object"?g.optionalData(JSON.stringify(e)):typeof e=="function"?g.optionalData(e()):String(e)}static sleep(e){return new Promise(t=>setTimeout(t,e))}}class E{static getParametersByName(e,t){t||(t=window.location.href),e=e.replace(/[[\]]/g,"\\$&");const i=new RegExp("[?&]"+e+"(=([^&#]*)|&|#|$)","gi"),s=[];let c;for(;(c=i.exec(t))!==null;)c[2]&&s.push(decodeURIComponent(c[2].replace(/\+/g," ")));return s.length>0?s:null}static externalHost(e){var t;return e.hostname!=location.hostname&&((t=e==null?void 0:e.protocol)==null?void 0:t.indexOf("http"))===0}}class r{static prefix(){return`__${a.TRACKER_FUNC_NAME}__`}static get(e){const t=`${r.prefix()}${e}`,i=document.cookie.split("; ").find(s=>s.startsWith(`${t}=`));return i?i.split("=")[1]:void 0}static set(e,t,i){const s=`${r.prefix()}${e}`,c=new Date;c.setTime(c.getTime()+i*60*1e3),document.cookie=`${s}=${t}; expires=${c.toUTCString()}; path=/`}static delete(e){const t=`${r.prefix()}${e}`;document.cookie=`${t}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/`}static clear(){document.cookie.split("; ").filter(e=>e.startsWith(r.prefix())).forEach(e=>{const t=e.split("=")[0];document.cookie=`${t}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/`})}static exists(e){return!!r.get(e)}static setUtms(){const e=k;let t=!1;for(let i=0;i<e.length;i++){const s=e[i];if(g.isPresent(E.getParametersByName(s,window.location.href))){t=!0;break}}if(t){let i;const s=[];for(let c=0;c<e.length;c++){const h=e[c];i=E.getParametersByName(h,window.location.href),s.push({[h]:encodeURIComponent(i)})}r.set(o.UTM,JSON.stringify(s),a.SESSION_EXPIRY_DAYS*24*60)}}static getUtms(){const e=r.get(o.UTM);return g.isPresent(e)?JSON.parse(e):{}}static createSession(e=!1){(e||!r.exists(o.SESSION))&&r.set(o.SESSION,g.guid(),a.SESSION_EXPIRY_DAYS*24*60),r.setUtms()}}class m{static isBot(){var i;if(typeof window>"u"||typeof navigator>"u")return!1;if(navigator.webdriver===!0)return n.debug("[CPIX] Bot detected: navigator.webdriver is true"),!0;const e=((i=navigator.userAgent)==null?void 0:i.toLowerCase())||"";return this.BOT_USER_AGENTS.some(s=>e.includes(s.toLowerCase()))?(n.debug("[CPIX] Bot detected: User agent matches bot pattern"),!0):this.hasMissingBrowserFeatures()?(n.debug("[CPIX] Bot detected: Missing browser features"),!0):this.isHeadlessBrowser()?(n.debug("[CPIX] Bot detected: Headless browser indicators"),!0):!1}static hasMissingBrowserFeatures(){const e=typeof navigator.plugins>"u"||navigator.plugins.length===0,t=typeof navigator.languages>"u"||navigator.languages.length===0;return!!(e&&t)}static isHeadlessBrowser(){var e,t;return(e=navigator.userAgent)!=null&&e.includes("HeadlessChrome")||window.outerWidth===0&&window.outerHeight===0&&window.innerWidth===0&&window.innerHeight===0&&(screen.width===0||screen.height===0)?!0:(typeof navigator.permissions>"u"&&((t=navigator.userAgent)!=null&&t.includes("Chrome")),!1)}}u(m,"BOT_USER_AGENTS",["googlebot","bingbot","slurp","duckduckbot","baiduspider","yandexbot","sogou","exabot","facebot","ia_archiver","siteauditbot","semrushbot","ahrefsbot","mj12bot","dotbot","megaindex","blexbot","petalbot","applebot","crawler","spider","scraper","headless","phantom","selenium","webdriver","puppeteer","playwright","chromium","chrome-lighthouse"]);class O{constructor(){u(this,"instances",[]);u(this,"initialized",!1);u(this,"sessionCreated",!1);u(this,"accessToken","");u(this,"metaParameters",{});u(this,"queue");u(this,"isBot",!1);if(!window)throw new Error("[CPIX] CarterAnalytics SDK can only be used in a browser environment");this.queue=new N({maxRetries:a.QUEUE_MAX_RETRIES,initialDelay:a.QUEUE_INITIAL_DELAY,consumerHandler:this.publishEventToServer.bind(this)})}async initialize(e){if(!e||e.length===0)throw new Error("[CPIX] At least one instance configuration is required for initialization");if(this.isBot=m.isBot(),this.isBot){n.debug("[CPIX] Bot detected - SDK will not track events for this session"),this.instances=e,a.DEBUG=this.instances[0].options.debug===!0,this.initialized=!0;return}this.instances=e,a.DEBUG=this.instances[0].options.debug===!0,a.API_URL=this.instances[0].options.tracker_server_url,a.USER_PROPERTIES=this.instances[0].options.user_properties||{},a.SESSION_EXPIRY_DAYS=this.instances[0].options.session_expiry_days||14,a.COMMON_PROPERTIES=this.instances[0].options.common_properties||{},r.exists(o.SESSION)||(r.createSession(),this.sessionCreated=!0);const t=r.get(o.SESSION);if(!r.exists(o.META_PARAMETERS))this.metaParameters=await this.generateMetaParameters(),r.set(o.META_PARAMETERS,JSON.stringify(this.metaParameters),60*24);else{const i=r.get(o.META_PARAMETERS);if(i)try{const s=JSON.parse(i);s.session!==t?(n.debug("Session ID mismatch detected, regenerating meta parameters"),this.metaParameters=await this.generateMetaParameters(),r.set(o.META_PARAMETERS,JSON.stringify(this.metaParameters),60*24)):this.metaParameters=s}catch(s){n.error("Failed to parse meta parameters, regenerating:",s),this.metaParameters=await this.generateMetaParameters(),r.set(o.META_PARAMETERS,JSON.stringify(this.metaParameters),60*24)}else this.metaParameters=await this.generateMetaParameters(),r.set(o.META_PARAMETERS,JSON.stringify(this.metaParameters),60*24)}if(r.setUtms(),this.initialized)throw new Error("[CPIX] CarterAnalytics SDK has already been initialized");if(!this.metaParameters)throw new Error("[CPIX] Meta parameters have not been generated");r.exists(o.ACCESS_TOKEN)||(this.accessToken=await d.aquireAccessToken(this.instances[0].client_id),r.set(o.ACCESS_TOKEN,this.accessToken,60*4)),this.initialized=!0,n.debug("CPIX Initialized"),n.debug("Carter Analytics SDK initialized with options:",this.instances),this.sessionCreated&&this.publishInit(),this.attachHistoryListener()}publishInit(){this.publish({event:"init",user_properties:a.USER_PROPERTIES,...this.metaParameters})}attachHistoryListener(){const e=history.pushState,t=history.replaceState,i=()=>{this.publish({event:"page_view",event_properties:{title:document.title,page:window.location.pathname,url:window.location.href},user_properties:a.USER_PROPERTIES,...this.metaParameters})};history.pushState=(...s)=>{e.apply(history,s),i()},history.replaceState=(...s)=>{t.apply(history,s),i()},window.addEventListener("popstate",i),i()}publish(e){if(!this.initialized)throw new Error("[CPIX] CarterAnalytics SDK has not been initialized. Please initialize before publishing events.");if(this.isBot||m.isBot()){n.debug("[CPIX] Event publishing blocked - bot detected");return}const t={...e,...this.metaParameters};if(t.utm_params=r.getUtms(),document.referrer&&(t.referrer=encodeURIComponent(document.referrer)),n.debug("Publishing event:",t),this.queue.publish(t),e.event==="logout"){r.delete(o.SESSION),r.delete(o.META_PARAMETERS),r.createSession(!0);const i=r.get(o.SESSION);if(!i){n.error("[CPIX] Failed to create new session on logout");return}this.generateMetaParameters().then(s=>{s.session!==i&&(n.error("[CPIX] Session ID mismatch after logout, updating meta parameters"),s.session=i),this.metaParameters=s,r.set(o.META_PARAMETERS,JSON.stringify(this.metaParameters),60*24),this.publishInit()})}}async generateMetaParameters(){if(!window)throw new Error("[CPIX] Meta parameters can only be generated in a browser environment");const e=await d.getDeviceNetworkParameters();return{client_id:this.instances[0].client_id,session:r.get(o.SESSION),location:{city:e.city,region:e.region,loc:e.loc,timezone:e.timezone,country:e.country},device:{category:d.getDeviceCategory(),brand:d.getDeviceManufacturer(),ip_address:e.ip_address,platform:d.getDevicePlatform(),browser_name:d.getBrowserName(),browser_version:d.getBrowserVersion(),screen_resolution:d.getScreenResolution(),viewport_size:d.getViewportSize(),language:d.getLanguage(),os_version:d.getOSVersion(),user_agent:d.getUserAgent(),cpix_sdk_version:a.version},referrer:encodeURIComponent(document.referrer)}}async publishEventToServer(e){try{e.timestamp=Date.now(),e.event_properties={url:window.location.href,...a.COMMON_PROPERTIES,...e.event_properties},e.device&&(e.device.cpix_sdk_version=a.version);const t=await fetch(`${a.API_URL}/api/event`,{method:"POST",body:JSON.stringify({event_data:e}),headers:{"Content-Type":"application/json",Authorization:`Bearer ${r.get(o.ACCESS_TOKEN)}`}});if(!t.ok)throw t.status===401&&(this.accessToken=await d.aquireAccessToken(this.instances[0].client_id),r.set(o.ACCESS_TOKEN,this.accessToken,60*4)),new Error("[CPIX] Failed to publish event");n.debug("Event published:",t.ok)}catch(t){throw n.error("Failed to publish event:",t),new Error("[CPIX] Failed to publish event")}}}const S=new O;typeof window<"u"&&(window.cpix=S);exports.CarterAnalytics=S;
package/dist/cpix.iife.js CHANGED
@@ -1 +1 @@
1
- var tracker=function(l){"use strict";var b=Object.defineProperty;var x=(l,d,p)=>d in l?b(l,d,{enumerable:!0,configurable:!0,writable:!0,value:p}):l[d]=p;var u=(l,d,p)=>(x(l,typeof d!="symbol"?d+"":d,p),p);const E={name:"@carter-rmn/cpix-js",version:"1.0.5",type:"module",files:["dist"],main:"dist/cpix.umd.cjs",module:"dist/cpix.js",types:"dist/cpix.d.ts",exports:{".":{import:"./dist/cpix.js",require:"./dist/cpix.umd.cjs"}},scripts:{dev:"vite",build:"tsc && vite build",preview:"vite preview"},devDependencies:{picocolors:"^1.0.0","rollup-plugin-visualizer":"^5.12.0",typescript:"^5.2.2",vite:"^5.2.0","vite-plugin-progress":"^0.0.7"},dependencies:{"vite-plugin-dts":"^3.8.1"}},n={DEBUG:!1,TRACKER_FUNC_NAME:"cpix",API_URL:"",QUEUE_MAX_RETRIES:3,QUEUE_INITIAL_DELAY:1e4,version:E.version,package:E.name,USER_PROPERTIES:{},SESSION_EXPIRY_DAYS:14,COMMON_PROPERTIES:{}},a={SESSION:"cpix_session",META_PARAMETERS:"cpix_meta_parameters",ACCESS_TOKEN:"cpix_access_token",UTM:"cpix_utm"},P=["utm_source","utm_medium","utm_term","utm_content","utm_campaign"],o=function(){const f=()=>n.DEBUG;return{info:function(...e){console.log(...e)},debug:function(...e){f()&&console.log(...e)},error:function(...e){console.error(...e)}}}();class _ extends EventTarget{constructor(t={maxRetries:3,initialDelay:1e4,consumerHandler:i=>(o.debug("Consuming event:",i),Promise.resolve())}){super();u(this,"dataQueue");u(this,"retryQueue");u(this,"maxRetries");u(this,"initialDelay");u(this,"publishEvent");u(this,"retryEvent");u(this,"handler");this.dataQueue=[],this.retryQueue=[],this.maxRetries=t.maxRetries,this.initialDelay=t.initialDelay,this.handler=t.consumerHandler,this.publishEvent=new Event("eventPublished"),this.retryEvent=new Event("retryMessage"),this.consume(),this.retry()}publish(t){o.debug("publishing event");const i={data:t,id:`${Date.now()+Math.random()}`,retryCount:0,retryDelay:this.initialDelay};this.dataQueue.push(i),this.dispatchEvent(this.publishEvent)}consume(){o.debug("Started Consumer Queue"),this.addEventListener("eventPublished",async()=>{for(;this.dataQueue.length>0;){const t=this.dataQueue.shift(),{data:i={}}=t;try{await this.handler(i),this.acknowledge(t==null?void 0:t.id)}catch(r){o.error("Failed to publish event:",r),this.scheduleRetry(t)}}})}scheduleRetry(t){if(t.retryCount>=this.maxRetries){o.error("Max retries reached for message:",t);return}setTimeout(()=>{this.retryQueue.push({...t,retryCount:t.retryCount+1,retryDelay:t.retryDelay*2}),this.dispatchEvent(this.retryEvent)},t.retryDelay)}acknowledge(t){this.dataQueue=this.dataQueue.filter(i=>i.id!==t)}retry(){o.debug("Started Retry Queue"),this.addEventListener("retryMessage",async()=>{for(;this.retryQueue.length>0;){const t=this.retryQueue.shift(),{data:i={}}=t;try{await this.handler(i),this.acknowledge(t==null?void 0:t.id)}catch(r){o.error("Failed to publish event:",r),this.scheduleRetry(t)}}})}}class m{static getBrowserInfo(){var r,c,g,S,v;const e=navigator.userAgent||"";let t,i;return/chrome/i.test(e)?(t="Chrome",i=(r=e.match(/chrome\/(\d+)/i))==null?void 0:r[1]):/firefox/i.test(e)?(t="Firefox",i=(c=e.match(/firefox\/(\d+)/i))==null?void 0:c[1]):/safari/i.test(e)?(t="Safari",i=(g=e.match(/version\/(\d+)/i))==null?void 0:g[1]):/edge/i.test(e)?(t="Edge",i=(S=e.match(/edge\/(\d+)/i))==null?void 0:S[1]):/trident/i.test(e)?(t="Internet Explorer",i=(v=e.match(/rv:(\d+)/i))==null?void 0:v[1]):(t="Unknown",i="Unknown"),`${t} ${i}`}static getDeviceCategory(){const e=navigator.userAgent;return/mobile/i.test(e)?"Mobile":/tablet/i.test(e)?"Tablet":"Desktop"}static getDevicePlatform(){const e=navigator.userAgent;return/android/i.test(e)?"Android":/iphone|ipad|ipod/i.test(e)?"iOS":/windows phone/i.test(e)?"Windows Phone":/mac|Macintosh/i.test(e)?"Mac":/windows|Microsoft/i.test(e)?"Windows":/linux/i.test(e)?"Linux":"Unknown"}static getDeviceManufacturer(){const e=navigator.userAgent;let t;return/iphone|ipad|ipod|mac|Macintosh/i.test(e)?t="Apple":/samsung/i.test(e)?t="Samsung":/google/i.test(e)?t="Google":/huawei/i.test(e)?t="Huawei":/xiaomi/i.test(e)?t="Xiaomi":/oneplus/i.test(e)?t="OnePlus":/dell/i.test(e)?t="Dell":/lenovo/i.test(e)?t="Lenovo":/acer/i.test(e)?t="Acer":/asus/i.test(e)?t="Asus":/toshiba/i.test(e)?t="Toshiba":t="Unknown",t}static async getDeviceNetworkParameters(){try{const e=await fetch(`${n.API_URL}/api/geolocation`),{data:t}=await e.json();return{city:t.city||"Unknown",region:t.region||"Unknown",country:t.country||"Unknown",timezone:t.timezone||"Unknown",loc:t.loc||"Unknown",ip_address:t.ip_address||"Unknown"}}catch(e){return o.error("Error retrieving device network parameters:",e),{city:"Unknown",region:"Unknown",country:"Unknown",timezone:"Unknown",loc:"Unknown",ip_address:"Unknown"}}}static async aquireAccessToken(e){try{return(await(await fetch(`${n.API_URL}/api/authenticate`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({accountId:e,metadata:{sdk:n.package,version:n.version,hostname:window.location.hostname}})})).json()).accessToken}catch(t){throw o.error("Error acquiring access token:",t),new Error("[CPIX] Authentication error")}}}class h{static isPresent(e){return typeof e<"u"&&e!==null&&e!==""}static now(){return 1*new Date().getTime()}static guid(){return E.version+"-xxxxxxxx-".replace(/[x]/g,function(e){const t=Math.random()*36|0;return(e=="x"?t:t&3|8).toString(36)})+(1*new Date().getTime()).toString(36)}static optionalData(e){return h.isPresent(e)===!1?"":typeof e=="object"?h.optionalData(JSON.stringify(e)):typeof e=="function"?h.optionalData(e()):String(e)}static sleep(e){return new Promise(t=>setTimeout(t,e))}}class w{static getParametersByName(e,t){t||(t=window.location.href),e=e.replace(/[[\]]/g,"\\$&");const i=new RegExp("[?&]"+e+"(=([^&#]*)|&|#|$)","gi"),r=[];let c;for(;(c=i.exec(t))!==null;)c[2]&&r.push(decodeURIComponent(c[2].replace(/\+/g," ")));return r.length>0?r:null}static externalHost(e){var t;return e.hostname!=location.hostname&&((t=e==null?void 0:e.protocol)==null?void 0:t.indexOf("http"))===0}}class s{static prefix(){return`__${n.TRACKER_FUNC_NAME}__`}static get(e){const t=`${s.prefix()}${e}`,i=document.cookie.split("; ").find(r=>r.startsWith(`${t}=`));return i?i.split("=")[1]:void 0}static set(e,t,i){const r=`${s.prefix()}${e}`,c=new Date;c.setTime(c.getTime()+i*60*1e3),document.cookie=`${r}=${t}; expires=${c.toUTCString()}; path=/`}static delete(e){const t=`${s.prefix()}${e}`;document.cookie=`${t}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/`}static clear(){document.cookie.split("; ").filter(e=>e.startsWith(s.prefix())).forEach(e=>{const t=e.split("=")[0];document.cookie=`${t}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/`})}static exists(e){return!!s.get(e)}static setUtms(){const e=P;let t=!1;for(let i=0;i<e.length;i++){const r=e[i];if(h.isPresent(w.getParametersByName(r,window.location.href))){t=!0;break}}if(t){let i;const r=[];for(let c=0;c<e.length;c++){const g=e[c];i=w.getParametersByName(g,window.location.href),r.push({[g]:encodeURIComponent(i)})}s.set(a.UTM,JSON.stringify(r),n.SESSION_EXPIRY_DAYS*24*60)}}static getUtms(){const e=s.get(a.UTM);return h.isPresent(e)?JSON.parse(e):{}}static createSession(){s.exists(a.SESSION)||s.set(a.SESSION,h.guid(),n.SESSION_EXPIRY_DAYS*24*60),s.setUtms()}}class A{constructor(){u(this,"instances",[]);u(this,"initialized",!1);u(this,"sessionCreated",!1);u(this,"accessToken","");u(this,"metaParameters",{});u(this,"queue");if(!window)throw new Error("[CPIX] CarterAnalytics SDK can only be used in a browser environment");this.queue=new _({maxRetries:n.QUEUE_MAX_RETRIES,initialDelay:n.QUEUE_INITIAL_DELAY,consumerHandler:this.publishEventToServer.bind(this)})}async initialize(e){if(!e||e.length===0)throw new Error("[CPIX] At least one instance configuration is required for initialization");if(this.instances=e,n.DEBUG=this.instances[0].options.debug===!0,n.API_URL=this.instances[0].options.tracker_server_url,n.USER_PROPERTIES=this.instances[0].options.user_properties||{},n.SESSION_EXPIRY_DAYS=this.instances[0].options.session_expiry_days||14,n.COMMON_PROPERTIES=this.instances[0].options.common_properties||{},s.exists(a.SESSION)||(s.createSession(),this.sessionCreated=!0),s.exists(a.META_PARAMETERS)||await this.generateMetaParameters().then(t=>{this.metaParameters=t,s.set("metaParameters",JSON.stringify(t),1440)}),s.setUtms(),this.metaParameters=JSON.parse(s.get("metaParameters")),this.initialized)throw new Error("[CPIX] CarterAnalytics SDK has already been initialized");if(!this.metaParameters)throw new Error("[CPIX] Meta parameters have not been generated");s.exists(a.ACCESS_TOKEN)||(this.accessToken=await m.aquireAccessToken(this.instances[0].client_id),s.set(a.ACCESS_TOKEN,this.accessToken,240)),this.initialized=!0,o.debug("CPIX Initialized"),o.debug("Carter Analytics SDK initialized with options:",this.instances),this.sessionCreated&&this.publishInit(),this.attachHistoryListener()}publishInit(){this.publish({event:"init",user_properties:n.USER_PROPERTIES,...this.metaParameters})}attachHistoryListener(){const e=history.pushState,t=history.replaceState,i=()=>{this.publish({event:"page_view",event_properties:{title:document.title,page:window.location.pathname,url:window.location.href},user_properties:n.USER_PROPERTIES,...this.metaParameters})};history.pushState=(...r)=>{e.apply(history,r),i()},history.replaceState=(...r)=>{t.apply(history,r),i()},window.addEventListener("popstate",i),i()}publish(e){if(!this.initialized)throw new Error("[CPIX] CarterAnalytics SDK has not been initialized. Please initialize before publishing events.");const t={...e,...this.metaParameters};t.utm_params=s.getUtms(),document.referrer&&(t.referrer=encodeURIComponent(document.referrer)),o.debug("Publishing event:",t),this.queue.publish(t),e.event==="logout"&&(s.delete(a.SESSION),s.delete(a.META_PARAMETERS),s.createSession(),this.generateMetaParameters().then(i=>{this.metaParameters=i,s.set(a.META_PARAMETERS,JSON.stringify(this.metaParameters),1440),this.publishInit()}))}async generateMetaParameters(){if(!window)throw new Error("[CPIX] Meta parameters can only be generated in a browser environment");const e=await m.getDeviceNetworkParameters();return{client_id:this.instances[0].client_id,session:s.get(a.SESSION),location:{city:e.city,region:e.region,loc:e.loc,timezone:e.timezone,country:e.country},device:{category:m.getDeviceCategory(),brand:m.getDeviceManufacturer(),ip_address:e.ip_address,platform:m.getDevicePlatform(),cpix_sdk_version:n.version},referrer:encodeURIComponent(document.referrer)}}async publishEventToServer(e){try{e.timestamp=Date.now(),e.event_properties={url:window.location.href,...n.COMMON_PROPERTIES,...e.event_properties},e.device&&(e.device.cpix_sdk_version=n.version);const t=await fetch(`${n.API_URL}/api/event`,{method:"POST",body:JSON.stringify({event_data:e}),headers:{"Content-Type":"application/json",Authorization:`Bearer ${s.get(a.ACCESS_TOKEN)}`}});if(!t.ok)throw t.status===401&&(this.accessToken=await m.aquireAccessToken(this.instances[0].client_id),s.set(a.ACCESS_TOKEN,this.accessToken,240)),new Error("[CPIX] Failed to publish event");o.debug("Event published:",t.ok)}catch(t){throw o.error("Failed to publish event:",t),new Error("[CPIX] Failed to publish event")}}}const y=new A;return typeof window<"u"&&(window.cpix=y),l.CarterAnalytics=y,Object.defineProperty(l,Symbol.toStringTag,{value:"Module"}),l}({});
1
+ var tracker=function(l){"use strict";var U=Object.defineProperty;var T=(l,h,f)=>h in l?U(l,h,{enumerable:!0,configurable:!0,writable:!0,value:f}):l[h]=f;var u=(l,h,f)=>(T(l,typeof h!="symbol"?h+"":h,f),f);const E={name:"@carter-rmn/cpix-js",version:"1.0.8",type:"module",files:["dist"],main:"dist/cpix.umd.cjs",module:"dist/cpix.js",types:"dist/cpix.d.ts",exports:{".":{import:"./dist/cpix.js",require:"./dist/cpix.umd.cjs"}},scripts:{dev:"vite",build:"tsc && vite build",preview:"vite preview"},devDependencies:{picocolors:"^1.0.0","rollup-plugin-visualizer":"^5.12.0",typescript:"^5.2.2",vite:"^5.2.0","vite-plugin-progress":"^0.0.7"},dependencies:{"vite-plugin-dts":"^3.8.1"}},a={DEBUG:!1,TRACKER_FUNC_NAME:"cpix",API_URL:"",QUEUE_MAX_RETRIES:3,QUEUE_INITIAL_DELAY:1e4,version:E.version,package:E.name,USER_PROPERTIES:{},SESSION_EXPIRY_DAYS:14,COMMON_PROPERTIES:{}},o={SESSION:"cpix_session",META_PARAMETERS:"cpix_meta_parameters",ACCESS_TOKEN:"cpix_access_token",UTM:"cpix_utm"},P=["utm_source","utm_medium","utm_term","utm_content","utm_campaign"],n=function(){const m=()=>a.DEBUG;return{info:function(...e){console.log(...e)},debug:function(...e){m()&&console.log(...e)},error:function(...e){console.error(...e)}}}();class A extends EventTarget{constructor(t={maxRetries:3,initialDelay:1e4,consumerHandler:i=>(n.debug("Consuming event:",i),Promise.resolve())}){super();u(this,"dataQueue");u(this,"retryQueue");u(this,"maxRetries");u(this,"initialDelay");u(this,"publishEvent");u(this,"retryEvent");u(this,"handler");this.dataQueue=[],this.retryQueue=[],this.maxRetries=t.maxRetries,this.initialDelay=t.initialDelay,this.handler=t.consumerHandler,this.publishEvent=new Event("eventPublished"),this.retryEvent=new Event("retryMessage"),this.consume(),this.retry()}publish(t){n.debug("publishing event");const i={data:t,id:`${Date.now()+Math.random()}`,retryCount:0,retryDelay:this.initialDelay};this.dataQueue.push(i),this.dispatchEvent(this.publishEvent)}consume(){n.debug("Started Consumer Queue"),this.addEventListener("eventPublished",async()=>{for(;this.dataQueue.length>0;){const t=this.dataQueue.shift(),{data:i={}}=t;try{await this.handler(i),this.acknowledge(t==null?void 0:t.id)}catch(s){n.error("Failed to publish event:",s),this.scheduleRetry(t)}}})}scheduleRetry(t){if(t.retryCount>=this.maxRetries){n.error("Max retries reached for message:",t);return}setTimeout(()=>{this.retryQueue.push({...t,retryCount:t.retryCount+1,retryDelay:t.retryDelay*2}),this.dispatchEvent(this.retryEvent)},t.retryDelay)}acknowledge(t){this.dataQueue=this.dataQueue.filter(i=>i.id!==t)}retry(){n.debug("Started Retry Queue"),this.addEventListener("retryMessage",async()=>{for(;this.retryQueue.length>0;){const t=this.retryQueue.shift(),{data:i={}}=t;try{await this.handler(i),this.acknowledge(t==null?void 0:t.id)}catch(s){n.error("Failed to publish event:",s),this.scheduleRetry(t)}}})}}class d{static getBrowserInfo(){var s,c,g,w,b;const e=navigator.userAgent||"";let t,i;return/chrome/i.test(e)?(t="Chrome",i=(s=e.match(/chrome\/(\d+)/i))==null?void 0:s[1]):/firefox/i.test(e)?(t="Firefox",i=(c=e.match(/firefox\/(\d+)/i))==null?void 0:c[1]):/safari/i.test(e)?(t="Safari",i=(g=e.match(/version\/(\d+)/i))==null?void 0:g[1]):/edge/i.test(e)?(t="Edge",i=(w=e.match(/edge\/(\d+)/i))==null?void 0:w[1]):/trident/i.test(e)?(t="Internet Explorer",i=(b=e.match(/rv:(\d+)/i))==null?void 0:b[1]):(t="Unknown",i="Unknown"),`${t} ${i}`}static getBrowserName(){const e=navigator.userAgent||"";let t;return/chrome/i.test(e)&&!/edge/i.test(e)?t="Chrome":/firefox/i.test(e)?t="Firefox":/safari/i.test(e)&&!/chrome/i.test(e)?t="Safari":/edge/i.test(e)?t="Edge":/trident/i.test(e)?t="Internet Explorer":t="Unknown",t}static getBrowserVersion(){var i,s,c,g,w;const e=navigator.userAgent||"";let t;return/chrome/i.test(e)&&!/edge/i.test(e)?t=((i=e.match(/chrome\/(\d+)/i))==null?void 0:i[1])||"Unknown":/firefox/i.test(e)?t=((s=e.match(/firefox\/(\d+)/i))==null?void 0:s[1])||"Unknown":/safari/i.test(e)&&!/chrome/i.test(e)?t=((c=e.match(/version\/(\d+)/i))==null?void 0:c[1])||"Unknown":/edge/i.test(e)?t=((g=e.match(/edge\/(\d+)/i))==null?void 0:g[1])||"Unknown":/trident/i.test(e)?t=((w=e.match(/rv:(\d+)/i))==null?void 0:w[1])||"Unknown":t="Unknown",t}static getScreenResolution(){return typeof window>"u"||!window.screen?"Unknown":`${window.screen.width}x${window.screen.height}`}static getViewportSize(){return typeof window>"u"?"Unknown":`${window.innerWidth}x${window.innerHeight}`}static getLanguage(){var e;return typeof navigator>"u"?"Unknown":navigator.language||((e=navigator.languages)==null?void 0:e[0])||"Unknown"}static getOSVersion(){const e=navigator.userAgent||"";let t="Unknown";if(/iphone|ipad|ipod/i.test(e)){const i=e.match(/os (\d+[._]\d+)/i);i&&(t=i[1].replace("_","."))}else if(/android/i.test(e)){const i=e.match(/android (\d+(\.\d+)?)/i);i&&(t=i[1])}else if(/windows/i.test(e))if(/windows nt 10.0/i.test(e))t="10";else if(/windows nt 6.3/i.test(e))t="8.1";else if(/windows nt 6.2/i.test(e))t="8";else if(/windows nt 6.1/i.test(e))t="7";else{const i=e.match(/windows nt (\d+\.\d+)/i);i&&(t=i[1])}else if(/mac|Macintosh/i.test(e)){const i=e.match(/mac os x (\d+[._]\d+)/i);i&&(t=i[1].replace("_","."))}return t}static getUserAgent(){return typeof navigator>"u"||!navigator.userAgent?"Unknown":navigator.userAgent}static getDeviceCategory(){const e=navigator.userAgent;return/mobile/i.test(e)?"Mobile":/tablet/i.test(e)?"Tablet":"Desktop"}static getDevicePlatform(){const e=navigator.userAgent;return/android/i.test(e)?"Android":/iphone|ipad|ipod/i.test(e)?"iOS":/windows phone/i.test(e)?"Windows Phone":/mac|Macintosh/i.test(e)?"Mac":/windows|Microsoft/i.test(e)?"Windows":/linux/i.test(e)?"Linux":"Unknown"}static getDeviceManufacturer(){const e=navigator.userAgent;let t;return/iphone|ipad|ipod|mac|Macintosh/i.test(e)?t="Apple":/samsung/i.test(e)?t="Samsung":/google/i.test(e)?t="Google":/huawei/i.test(e)?t="Huawei":/xiaomi/i.test(e)?t="Xiaomi":/oneplus/i.test(e)?t="OnePlus":/dell/i.test(e)?t="Dell":/lenovo/i.test(e)?t="Lenovo":/acer/i.test(e)?t="Acer":/asus/i.test(e)?t="Asus":/toshiba/i.test(e)?t="Toshiba":t="Unknown",t}static async getDeviceNetworkParameters(){try{const e=await fetch(`${a.API_URL}/api/geolocation`),{data:t}=await e.json();return{city:t.city||"Unknown",region:t.region||"Unknown",country:t.country||"Unknown",timezone:t.timezone||"Unknown",loc:t.loc||"Unknown",ip_address:t.ip_address||"Unknown"}}catch(e){return n.error("Error retrieving device network parameters:",e),{city:"Unknown",region:"Unknown",country:"Unknown",timezone:"Unknown",loc:"Unknown",ip_address:"Unknown"}}}static async aquireAccessToken(e){try{return(await(await fetch(`${a.API_URL}/api/authenticate`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({accountId:e,metadata:{sdk:a.package,version:a.version,hostname:window.location.hostname}})})).json()).accessToken}catch(t){throw n.error("Error acquiring access token:",t),new Error("[CPIX] Authentication error")}}}class p{static isPresent(e){return typeof e<"u"&&e!==null&&e!==""}static now(){return 1*new Date().getTime()}static guid(){return E.version+"-xxxxxxxx-".replace(/[x]/g,function(e){const t=Math.random()*36|0;return(e=="x"?t:t&3|8).toString(36)})+(1*new Date().getTime()).toString(36)}static optionalData(e){return p.isPresent(e)===!1?"":typeof e=="object"?p.optionalData(JSON.stringify(e)):typeof e=="function"?p.optionalData(e()):String(e)}static sleep(e){return new Promise(t=>setTimeout(t,e))}}class v{static getParametersByName(e,t){t||(t=window.location.href),e=e.replace(/[[\]]/g,"\\$&");const i=new RegExp("[?&]"+e+"(=([^&#]*)|&|#|$)","gi"),s=[];let c;for(;(c=i.exec(t))!==null;)c[2]&&s.push(decodeURIComponent(c[2].replace(/\+/g," ")));return s.length>0?s:null}static externalHost(e){var t;return e.hostname!=location.hostname&&((t=e==null?void 0:e.protocol)==null?void 0:t.indexOf("http"))===0}}class r{static prefix(){return`__${a.TRACKER_FUNC_NAME}__`}static get(e){const t=`${r.prefix()}${e}`,i=document.cookie.split("; ").find(s=>s.startsWith(`${t}=`));return i?i.split("=")[1]:void 0}static set(e,t,i){const s=`${r.prefix()}${e}`,c=new Date;c.setTime(c.getTime()+i*60*1e3),document.cookie=`${s}=${t}; expires=${c.toUTCString()}; path=/`}static delete(e){const t=`${r.prefix()}${e}`;document.cookie=`${t}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/`}static clear(){document.cookie.split("; ").filter(e=>e.startsWith(r.prefix())).forEach(e=>{const t=e.split("=")[0];document.cookie=`${t}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/`})}static exists(e){return!!r.get(e)}static setUtms(){const e=P;let t=!1;for(let i=0;i<e.length;i++){const s=e[i];if(p.isPresent(v.getParametersByName(s,window.location.href))){t=!0;break}}if(t){let i;const s=[];for(let c=0;c<e.length;c++){const g=e[c];i=v.getParametersByName(g,window.location.href),s.push({[g]:encodeURIComponent(i)})}r.set(o.UTM,JSON.stringify(s),a.SESSION_EXPIRY_DAYS*24*60)}}static getUtms(){const e=r.get(o.UTM);return p.isPresent(e)?JSON.parse(e):{}}static createSession(e=!1){(e||!r.exists(o.SESSION))&&r.set(o.SESSION,p.guid(),a.SESSION_EXPIRY_DAYS*24*60),r.setUtms()}}class S{static isBot(){var i;if(typeof window>"u"||typeof navigator>"u")return!1;if(navigator.webdriver===!0)return n.debug("[CPIX] Bot detected: navigator.webdriver is true"),!0;const e=((i=navigator.userAgent)==null?void 0:i.toLowerCase())||"";return this.BOT_USER_AGENTS.some(s=>e.includes(s.toLowerCase()))?(n.debug("[CPIX] Bot detected: User agent matches bot pattern"),!0):this.hasMissingBrowserFeatures()?(n.debug("[CPIX] Bot detected: Missing browser features"),!0):this.isHeadlessBrowser()?(n.debug("[CPIX] Bot detected: Headless browser indicators"),!0):!1}static hasMissingBrowserFeatures(){const e=typeof navigator.plugins>"u"||navigator.plugins.length===0,t=typeof navigator.languages>"u"||navigator.languages.length===0;return!!(e&&t)}static isHeadlessBrowser(){var e,t;return(e=navigator.userAgent)!=null&&e.includes("HeadlessChrome")||window.outerWidth===0&&window.outerHeight===0&&window.innerWidth===0&&window.innerHeight===0&&(screen.width===0||screen.height===0)?!0:(typeof navigator.permissions>"u"&&((t=navigator.userAgent)!=null&&t.includes("Chrome")),!1)}}u(S,"BOT_USER_AGENTS",["googlebot","bingbot","slurp","duckduckbot","baiduspider","yandexbot","sogou","exabot","facebot","ia_archiver","siteauditbot","semrushbot","ahrefsbot","mj12bot","dotbot","megaindex","blexbot","petalbot","applebot","crawler","spider","scraper","headless","phantom","selenium","webdriver","puppeteer","playwright","chromium","chrome-lighthouse"]);class _{constructor(){u(this,"instances",[]);u(this,"initialized",!1);u(this,"sessionCreated",!1);u(this,"accessToken","");u(this,"metaParameters",{});u(this,"queue");u(this,"isBot",!1);if(!window)throw new Error("[CPIX] CarterAnalytics SDK can only be used in a browser environment");this.queue=new A({maxRetries:a.QUEUE_MAX_RETRIES,initialDelay:a.QUEUE_INITIAL_DELAY,consumerHandler:this.publishEventToServer.bind(this)})}async initialize(e){if(!e||e.length===0)throw new Error("[CPIX] At least one instance configuration is required for initialization");if(this.isBot=S.isBot(),this.isBot){n.debug("[CPIX] Bot detected - SDK will not track events for this session"),this.instances=e,a.DEBUG=this.instances[0].options.debug===!0,this.initialized=!0;return}this.instances=e,a.DEBUG=this.instances[0].options.debug===!0,a.API_URL=this.instances[0].options.tracker_server_url,a.USER_PROPERTIES=this.instances[0].options.user_properties||{},a.SESSION_EXPIRY_DAYS=this.instances[0].options.session_expiry_days||14,a.COMMON_PROPERTIES=this.instances[0].options.common_properties||{},r.exists(o.SESSION)||(r.createSession(),this.sessionCreated=!0);const t=r.get(o.SESSION);if(!r.exists(o.META_PARAMETERS))this.metaParameters=await this.generateMetaParameters(),r.set(o.META_PARAMETERS,JSON.stringify(this.metaParameters),1440);else{const i=r.get(o.META_PARAMETERS);if(i)try{const s=JSON.parse(i);s.session!==t?(n.debug("Session ID mismatch detected, regenerating meta parameters"),this.metaParameters=await this.generateMetaParameters(),r.set(o.META_PARAMETERS,JSON.stringify(this.metaParameters),1440)):this.metaParameters=s}catch(s){n.error("Failed to parse meta parameters, regenerating:",s),this.metaParameters=await this.generateMetaParameters(),r.set(o.META_PARAMETERS,JSON.stringify(this.metaParameters),1440)}else this.metaParameters=await this.generateMetaParameters(),r.set(o.META_PARAMETERS,JSON.stringify(this.metaParameters),1440)}if(r.setUtms(),this.initialized)throw new Error("[CPIX] CarterAnalytics SDK has already been initialized");if(!this.metaParameters)throw new Error("[CPIX] Meta parameters have not been generated");r.exists(o.ACCESS_TOKEN)||(this.accessToken=await d.aquireAccessToken(this.instances[0].client_id),r.set(o.ACCESS_TOKEN,this.accessToken,240)),this.initialized=!0,n.debug("CPIX Initialized"),n.debug("Carter Analytics SDK initialized with options:",this.instances),this.sessionCreated&&this.publishInit(),this.attachHistoryListener()}publishInit(){this.publish({event:"init",user_properties:a.USER_PROPERTIES,...this.metaParameters})}attachHistoryListener(){const e=history.pushState,t=history.replaceState,i=()=>{this.publish({event:"page_view",event_properties:{title:document.title,page:window.location.pathname,url:window.location.href},user_properties:a.USER_PROPERTIES,...this.metaParameters})};history.pushState=(...s)=>{e.apply(history,s),i()},history.replaceState=(...s)=>{t.apply(history,s),i()},window.addEventListener("popstate",i),i()}publish(e){if(!this.initialized)throw new Error("[CPIX] CarterAnalytics SDK has not been initialized. Please initialize before publishing events.");if(this.isBot||S.isBot()){n.debug("[CPIX] Event publishing blocked - bot detected");return}const t={...e,...this.metaParameters};if(t.utm_params=r.getUtms(),document.referrer&&(t.referrer=encodeURIComponent(document.referrer)),n.debug("Publishing event:",t),this.queue.publish(t),e.event==="logout"){r.delete(o.SESSION),r.delete(o.META_PARAMETERS),r.createSession(!0);const i=r.get(o.SESSION);if(!i){n.error("[CPIX] Failed to create new session on logout");return}this.generateMetaParameters().then(s=>{s.session!==i&&(n.error("[CPIX] Session ID mismatch after logout, updating meta parameters"),s.session=i),this.metaParameters=s,r.set(o.META_PARAMETERS,JSON.stringify(this.metaParameters),1440),this.publishInit()})}}async generateMetaParameters(){if(!window)throw new Error("[CPIX] Meta parameters can only be generated in a browser environment");const e=await d.getDeviceNetworkParameters();return{client_id:this.instances[0].client_id,session:r.get(o.SESSION),location:{city:e.city,region:e.region,loc:e.loc,timezone:e.timezone,country:e.country},device:{category:d.getDeviceCategory(),brand:d.getDeviceManufacturer(),ip_address:e.ip_address,platform:d.getDevicePlatform(),browser_name:d.getBrowserName(),browser_version:d.getBrowserVersion(),screen_resolution:d.getScreenResolution(),viewport_size:d.getViewportSize(),language:d.getLanguage(),os_version:d.getOSVersion(),user_agent:d.getUserAgent(),cpix_sdk_version:a.version},referrer:encodeURIComponent(document.referrer)}}async publishEventToServer(e){try{e.timestamp=Date.now(),e.event_properties={url:window.location.href,...a.COMMON_PROPERTIES,...e.event_properties},e.device&&(e.device.cpix_sdk_version=a.version);const t=await fetch(`${a.API_URL}/api/event`,{method:"POST",body:JSON.stringify({event_data:e}),headers:{"Content-Type":"application/json",Authorization:`Bearer ${r.get(o.ACCESS_TOKEN)}`}});if(!t.ok)throw t.status===401&&(this.accessToken=await d.aquireAccessToken(this.instances[0].client_id),r.set(o.ACCESS_TOKEN,this.accessToken,240)),new Error("[CPIX] Failed to publish event");n.debug("Event published:",t.ok)}catch(t){throw n.error("Failed to publish event:",t),new Error("[CPIX] Failed to publish event")}}}const y=new _;return typeof window<"u"&&(window.cpix=y),l.CarterAnalytics=y,Object.defineProperty(l,Symbol.toStringTag,{value:"Module"}),l}({});
package/dist/cpix.js CHANGED
@@ -1,14 +1,14 @@
1
- var w = Object.defineProperty;
2
- var y = (l, e, t) => e in l ? w(l, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : l[e] = t;
3
- var o = (l, e, t) => (y(l, typeof e != "symbol" ? e + "" : e, t), t);
4
- const S = "@carter-rmn/cpix-js", v = "1.0.5", P = "module", _ = [
1
+ var S = Object.defineProperty;
2
+ var v = (l, e, t) => e in l ? S(l, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : l[e] = t;
3
+ var u = (l, e, t) => (v(l, typeof e != "symbol" ? e + "" : e, t), t);
4
+ const y = "@carter-rmn/cpix-js", b = "1.0.8", A = "module", P = [
5
5
  "dist"
6
- ], x = "dist/cpix.umd.cjs", A = "dist/cpix.js", R = "dist/cpix.d.ts", T = {
6
+ ], _ = "dist/cpix.umd.cjs", U = "dist/cpix.js", x = "dist/cpix.d.ts", R = {
7
7
  ".": {
8
8
  import: "./dist/cpix.js",
9
9
  require: "./dist/cpix.umd.cjs"
10
10
  }
11
- }, b = {
11
+ }, T = {
12
12
  dev: "vite",
13
13
  build: "tsc && vite build",
14
14
  preview: "vite preview"
@@ -18,44 +18,44 @@ const S = "@carter-rmn/cpix-js", v = "1.0.5", P = "module", _ = [
18
18
  typescript: "^5.2.2",
19
19
  vite: "^5.2.0",
20
20
  "vite-plugin-progress": "^0.0.7"
21
- }, U = {
21
+ }, C = {
22
22
  "vite-plugin-dts": "^3.8.1"
23
- }, m = {
24
- name: S,
25
- version: v,
26
- type: P,
27
- files: _,
28
- main: x,
29
- module: A,
30
- types: R,
31
- exports: T,
32
- scripts: b,
23
+ }, f = {
24
+ name: y,
25
+ version: b,
26
+ type: A,
27
+ files: P,
28
+ main: _,
29
+ module: U,
30
+ types: x,
31
+ exports: R,
32
+ scripts: T,
33
33
  devDependencies: I,
34
- dependencies: U
35
- }, n = {
34
+ dependencies: C
35
+ }, a = {
36
36
  DEBUG: !1,
37
37
  TRACKER_FUNC_NAME: "cpix",
38
38
  API_URL: "",
39
39
  QUEUE_MAX_RETRIES: 3,
40
40
  QUEUE_INITIAL_DELAY: 1e4,
41
- version: m.version,
42
- package: m.name,
41
+ version: f.version,
42
+ package: f.name,
43
43
  USER_PROPERTIES: {},
44
44
  SESSION_EXPIRY_DAYS: 14,
45
45
  COMMON_PROPERTIES: {}
46
- }, c = {
46
+ }, o = {
47
47
  SESSION: "cpix_session",
48
48
  META_PARAMETERS: "cpix_meta_parameters",
49
49
  ACCESS_TOKEN: "cpix_access_token",
50
50
  UTM: "cpix_utm"
51
- }, C = [
51
+ }, M = [
52
52
  "utm_source",
53
53
  "utm_medium",
54
54
  "utm_term",
55
55
  "utm_content",
56
56
  "utm_campaign"
57
- ], u = /* @__PURE__ */ function() {
58
- const l = () => n.DEBUG;
57
+ ], n = /* @__PURE__ */ function() {
58
+ const l = () => a.DEBUG;
59
59
  return {
60
60
  info: function(...e) {
61
61
  console.log(...e);
@@ -68,24 +68,24 @@ const S = "@carter-rmn/cpix-js", v = "1.0.5", P = "module", _ = [
68
68
  }
69
69
  };
70
70
  }();
71
- class O extends EventTarget {
71
+ class k extends EventTarget {
72
72
  constructor(t = {
73
73
  maxRetries: 3,
74
74
  initialDelay: 1e4,
75
- consumerHandler: (i) => (u.debug("Consuming event:", i), Promise.resolve())
75
+ consumerHandler: (i) => (n.debug("Consuming event:", i), Promise.resolve())
76
76
  }) {
77
77
  super();
78
- o(this, "dataQueue");
79
- o(this, "retryQueue");
80
- o(this, "maxRetries");
81
- o(this, "initialDelay");
82
- o(this, "publishEvent");
83
- o(this, "retryEvent");
84
- o(this, "handler");
78
+ u(this, "dataQueue");
79
+ u(this, "retryQueue");
80
+ u(this, "maxRetries");
81
+ u(this, "initialDelay");
82
+ u(this, "publishEvent");
83
+ u(this, "retryEvent");
84
+ u(this, "handler");
85
85
  this.dataQueue = [], this.retryQueue = [], this.maxRetries = t.maxRetries, this.initialDelay = t.initialDelay, this.handler = t.consumerHandler, this.publishEvent = new Event("eventPublished"), this.retryEvent = new Event("retryMessage"), this.consume(), this.retry();
86
86
  }
87
87
  publish(t) {
88
- u.debug("publishing event");
88
+ n.debug("publishing event");
89
89
  const i = {
90
90
  data: t,
91
91
  id: `${Date.now() + Math.random()}`,
@@ -95,20 +95,20 @@ class O extends EventTarget {
95
95
  this.dataQueue.push(i), this.dispatchEvent(this.publishEvent);
96
96
  }
97
97
  consume() {
98
- u.debug("Started Consumer Queue"), this.addEventListener("eventPublished", async () => {
98
+ n.debug("Started Consumer Queue"), this.addEventListener("eventPublished", async () => {
99
99
  for (; this.dataQueue.length > 0; ) {
100
100
  const t = this.dataQueue.shift(), { data: i = {} } = t;
101
101
  try {
102
102
  await this.handler(i), this.acknowledge(t == null ? void 0 : t.id);
103
- } catch (r) {
104
- u.error("Failed to publish event:", r), this.scheduleRetry(t);
103
+ } catch (s) {
104
+ n.error("Failed to publish event:", s), this.scheduleRetry(t);
105
105
  }
106
106
  }
107
107
  });
108
108
  }
109
109
  scheduleRetry(t) {
110
110
  if (t.retryCount >= this.maxRetries) {
111
- u.error("Max retries reached for message:", t);
111
+ n.error("Max retries reached for message:", t);
112
112
  return;
113
113
  }
114
114
  setTimeout(() => {
@@ -123,13 +123,13 @@ class O extends EventTarget {
123
123
  this.dataQueue = this.dataQueue.filter((i) => i.id !== t);
124
124
  }
125
125
  retry() {
126
- u.debug("Started Retry Queue"), this.addEventListener("retryMessage", async () => {
126
+ n.debug("Started Retry Queue"), this.addEventListener("retryMessage", async () => {
127
127
  for (; this.retryQueue.length > 0; ) {
128
128
  const t = this.retryQueue.shift(), { data: i = {} } = t;
129
129
  try {
130
130
  await this.handler(i), this.acknowledge(t == null ? void 0 : t.id);
131
- } catch (r) {
132
- u.error("Failed to publish event:", r), this.scheduleRetry(t);
131
+ } catch (s) {
132
+ n.error("Failed to publish event:", s), this.scheduleRetry(t);
133
133
  }
134
134
  }
135
135
  });
@@ -137,10 +137,62 @@ class O extends EventTarget {
137
137
  }
138
138
  class d {
139
139
  static getBrowserInfo() {
140
- var r, a, p, f, E;
140
+ var s, c, h, p, w;
141
141
  const e = navigator.userAgent || "";
142
142
  let t, i;
143
- return /chrome/i.test(e) ? (t = "Chrome", i = (r = e.match(/chrome\/(\d+)/i)) == null ? void 0 : r[1]) : /firefox/i.test(e) ? (t = "Firefox", i = (a = e.match(/firefox\/(\d+)/i)) == null ? void 0 : a[1]) : /safari/i.test(e) ? (t = "Safari", i = (p = e.match(/version\/(\d+)/i)) == null ? void 0 : p[1]) : /edge/i.test(e) ? (t = "Edge", i = (f = e.match(/edge\/(\d+)/i)) == null ? void 0 : f[1]) : /trident/i.test(e) ? (t = "Internet Explorer", i = (E = e.match(/rv:(\d+)/i)) == null ? void 0 : E[1]) : (t = "Unknown", i = "Unknown"), `${t} ${i}`;
143
+ return /chrome/i.test(e) ? (t = "Chrome", i = (s = e.match(/chrome\/(\d+)/i)) == null ? void 0 : s[1]) : /firefox/i.test(e) ? (t = "Firefox", i = (c = e.match(/firefox\/(\d+)/i)) == null ? void 0 : c[1]) : /safari/i.test(e) ? (t = "Safari", i = (h = e.match(/version\/(\d+)/i)) == null ? void 0 : h[1]) : /edge/i.test(e) ? (t = "Edge", i = (p = e.match(/edge\/(\d+)/i)) == null ? void 0 : p[1]) : /trident/i.test(e) ? (t = "Internet Explorer", i = (w = e.match(/rv:(\d+)/i)) == null ? void 0 : w[1]) : (t = "Unknown", i = "Unknown"), `${t} ${i}`;
144
+ }
145
+ static getBrowserName() {
146
+ const e = navigator.userAgent || "";
147
+ let t;
148
+ return /chrome/i.test(e) && !/edge/i.test(e) ? t = "Chrome" : /firefox/i.test(e) ? t = "Firefox" : /safari/i.test(e) && !/chrome/i.test(e) ? t = "Safari" : /edge/i.test(e) ? t = "Edge" : /trident/i.test(e) ? t = "Internet Explorer" : t = "Unknown", t;
149
+ }
150
+ static getBrowserVersion() {
151
+ var i, s, c, h, p;
152
+ const e = navigator.userAgent || "";
153
+ let t;
154
+ return /chrome/i.test(e) && !/edge/i.test(e) ? t = ((i = e.match(/chrome\/(\d+)/i)) == null ? void 0 : i[1]) || "Unknown" : /firefox/i.test(e) ? t = ((s = e.match(/firefox\/(\d+)/i)) == null ? void 0 : s[1]) || "Unknown" : /safari/i.test(e) && !/chrome/i.test(e) ? t = ((c = e.match(/version\/(\d+)/i)) == null ? void 0 : c[1]) || "Unknown" : /edge/i.test(e) ? t = ((h = e.match(/edge\/(\d+)/i)) == null ? void 0 : h[1]) || "Unknown" : /trident/i.test(e) ? t = ((p = e.match(/rv:(\d+)/i)) == null ? void 0 : p[1]) || "Unknown" : t = "Unknown", t;
155
+ }
156
+ static getScreenResolution() {
157
+ return typeof window > "u" || !window.screen ? "Unknown" : `${window.screen.width}x${window.screen.height}`;
158
+ }
159
+ static getViewportSize() {
160
+ return typeof window > "u" ? "Unknown" : `${window.innerWidth}x${window.innerHeight}`;
161
+ }
162
+ static getLanguage() {
163
+ var e;
164
+ return typeof navigator > "u" ? "Unknown" : navigator.language || ((e = navigator.languages) == null ? void 0 : e[0]) || "Unknown";
165
+ }
166
+ static getOSVersion() {
167
+ const e = navigator.userAgent || "";
168
+ let t = "Unknown";
169
+ if (/iphone|ipad|ipod/i.test(e)) {
170
+ const i = e.match(/os (\d+[._]\d+)/i);
171
+ i && (t = i[1].replace("_", "."));
172
+ } else if (/android/i.test(e)) {
173
+ const i = e.match(/android (\d+(\.\d+)?)/i);
174
+ i && (t = i[1]);
175
+ } else if (/windows/i.test(e))
176
+ if (/windows nt 10.0/i.test(e))
177
+ t = "10";
178
+ else if (/windows nt 6.3/i.test(e))
179
+ t = "8.1";
180
+ else if (/windows nt 6.2/i.test(e))
181
+ t = "8";
182
+ else if (/windows nt 6.1/i.test(e))
183
+ t = "7";
184
+ else {
185
+ const i = e.match(/windows nt (\d+\.\d+)/i);
186
+ i && (t = i[1]);
187
+ }
188
+ else if (/mac|Macintosh/i.test(e)) {
189
+ const i = e.match(/mac os x (\d+[._]\d+)/i);
190
+ i && (t = i[1].replace("_", "."));
191
+ }
192
+ return t;
193
+ }
194
+ static getUserAgent() {
195
+ return typeof navigator > "u" || !navigator.userAgent ? "Unknown" : navigator.userAgent;
144
196
  }
145
197
  static getDeviceCategory() {
146
198
  const e = navigator.userAgent;
@@ -157,7 +209,7 @@ class d {
157
209
  }
158
210
  static async getDeviceNetworkParameters() {
159
211
  try {
160
- const e = await fetch(`${n.API_URL}/api/geolocation`), { data: t } = await e.json();
212
+ const e = await fetch(`${a.API_URL}/api/geolocation`), { data: t } = await e.json();
161
213
  return {
162
214
  city: t.city || "Unknown",
163
215
  region: t.region || "Unknown",
@@ -167,7 +219,7 @@ class d {
167
219
  ip_address: t.ip_address || "Unknown"
168
220
  };
169
221
  } catch (e) {
170
- return u.error("Error retrieving device network parameters:", e), {
222
+ return n.error("Error retrieving device network parameters:", e), {
171
223
  city: "Unknown",
172
224
  region: "Unknown",
173
225
  country: "Unknown",
@@ -179,7 +231,7 @@ class d {
179
231
  }
180
232
  static async aquireAccessToken(e) {
181
233
  try {
182
- return (await (await fetch(`${n.API_URL}/api/authenticate`, {
234
+ return (await (await fetch(`${a.API_URL}/api/authenticate`, {
183
235
  method: "POST",
184
236
  headers: {
185
237
  "Content-Type": "application/json"
@@ -187,18 +239,18 @@ class d {
187
239
  body: JSON.stringify({
188
240
  accountId: e,
189
241
  metadata: {
190
- sdk: n.package,
191
- version: n.version,
242
+ sdk: a.package,
243
+ version: a.version,
192
244
  hostname: window.location.hostname
193
245
  }
194
246
  })
195
247
  })).json()).accessToken;
196
248
  } catch (t) {
197
- throw u.error("Error acquiring access token:", t), new Error("[CPIX] Authentication error");
249
+ throw n.error("Error acquiring access token:", t), new Error("[CPIX] Authentication error");
198
250
  }
199
251
  }
200
252
  }
201
- class h {
253
+ class g {
202
254
  static isPresent(e) {
203
255
  return typeof e < "u" && e !== null && e !== "";
204
256
  }
@@ -206,27 +258,27 @@ class h {
206
258
  return 1 * (/* @__PURE__ */ new Date()).getTime();
207
259
  }
208
260
  static guid() {
209
- return m.version + "-xxxxxxxx-".replace(/[x]/g, function(e) {
261
+ return f.version + "-xxxxxxxx-".replace(/[x]/g, function(e) {
210
262
  const t = Math.random() * 36 | 0;
211
263
  return (e == "x" ? t : t & 3 | 8).toString(36);
212
264
  }) + (1 * (/* @__PURE__ */ new Date()).getTime()).toString(36);
213
265
  }
214
266
  // reduces all optional data down to a string
215
267
  static optionalData(e) {
216
- return h.isPresent(e) === !1 ? "" : typeof e == "object" ? h.optionalData(JSON.stringify(e)) : typeof e == "function" ? h.optionalData(e()) : String(e);
268
+ return g.isPresent(e) === !1 ? "" : typeof e == "object" ? g.optionalData(JSON.stringify(e)) : typeof e == "function" ? g.optionalData(e()) : String(e);
217
269
  }
218
270
  static sleep(e) {
219
271
  return new Promise((t) => setTimeout(t, e));
220
272
  }
221
273
  }
222
- class g {
274
+ class E {
223
275
  static getParametersByName(e, t) {
224
276
  t || (t = window.location.href), e = e.replace(/[[\]]/g, "\\$&");
225
- const i = new RegExp("[?&]" + e + "(=([^&#]*)|&|#|$)", "gi"), r = [];
226
- let a;
227
- for (; (a = i.exec(t)) !== null; )
228
- a[2] && r.push(decodeURIComponent(a[2].replace(/\+/g, " ")));
229
- return r.length > 0 ? r : null;
277
+ const i = new RegExp("[?&]" + e + "(=([^&#]*)|&|#|$)", "gi"), s = [];
278
+ let c;
279
+ for (; (c = i.exec(t)) !== null; )
280
+ c[2] && s.push(decodeURIComponent(c[2].replace(/\+/g, " ")));
281
+ return s.length > 0 ? s : null;
230
282
  }
231
283
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
232
284
  static externalHost(e) {
@@ -234,84 +286,153 @@ class g {
234
286
  return e.hostname != location.hostname && ((t = e == null ? void 0 : e.protocol) == null ? void 0 : t.indexOf("http")) === 0;
235
287
  }
236
288
  }
237
- class s {
289
+ class r {
238
290
  static prefix() {
239
- return `__${n.TRACKER_FUNC_NAME}__`;
291
+ return `__${a.TRACKER_FUNC_NAME}__`;
240
292
  }
241
293
  static get(e) {
242
- const t = `${s.prefix()}${e}`, i = document.cookie.split("; ").find((r) => r.startsWith(`${t}=`));
294
+ const t = `${r.prefix()}${e}`, i = document.cookie.split("; ").find((s) => s.startsWith(`${t}=`));
243
295
  return i ? i.split("=")[1] : void 0;
244
296
  }
245
297
  static set(e, t, i) {
246
- const r = `${s.prefix()}${e}`, a = /* @__PURE__ */ new Date();
247
- a.setTime(a.getTime() + i * 60 * 1e3), document.cookie = `${r}=${t}; expires=${a.toUTCString()}; path=/`;
298
+ const s = `${r.prefix()}${e}`, c = /* @__PURE__ */ new Date();
299
+ c.setTime(c.getTime() + i * 60 * 1e3), document.cookie = `${s}=${t}; expires=${c.toUTCString()}; path=/`;
248
300
  }
249
301
  static delete(e) {
250
- const t = `${s.prefix()}${e}`;
302
+ const t = `${r.prefix()}${e}`;
251
303
  document.cookie = `${t}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/`;
252
304
  }
253
305
  static clear() {
254
- document.cookie.split("; ").filter((e) => e.startsWith(s.prefix())).forEach((e) => {
306
+ document.cookie.split("; ").filter((e) => e.startsWith(r.prefix())).forEach((e) => {
255
307
  const t = e.split("=")[0];
256
308
  document.cookie = `${t}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/`;
257
309
  });
258
310
  }
259
311
  static exists(e) {
260
- return !!s.get(e);
312
+ return !!r.get(e);
261
313
  }
262
314
  static setUtms() {
263
- const e = C;
315
+ const e = M;
264
316
  let t = !1;
265
317
  for (let i = 0; i < e.length; i++) {
266
- const r = e[i];
267
- if (h.isPresent(g.getParametersByName(r, window.location.href))) {
318
+ const s = e[i];
319
+ if (g.isPresent(E.getParametersByName(s, window.location.href))) {
268
320
  t = !0;
269
321
  break;
270
322
  }
271
323
  }
272
324
  if (t) {
273
325
  let i;
274
- const r = [];
275
- for (let a = 0; a < e.length; a++) {
276
- const p = e[a];
277
- i = g.getParametersByName(p, window.location.href), r.push({
278
- [p]: encodeURIComponent(i)
326
+ const s = [];
327
+ for (let c = 0; c < e.length; c++) {
328
+ const h = e[c];
329
+ i = E.getParametersByName(h, window.location.href), s.push({
330
+ [h]: encodeURIComponent(i)
279
331
  });
280
332
  }
281
- s.set(
282
- c.UTM,
283
- JSON.stringify(r),
284
- n.SESSION_EXPIRY_DAYS * 24 * 60
333
+ r.set(
334
+ o.UTM,
335
+ JSON.stringify(s),
336
+ a.SESSION_EXPIRY_DAYS * 24 * 60
285
337
  );
286
338
  }
287
339
  }
288
340
  static getUtms() {
289
- const e = s.get(c.UTM);
290
- return h.isPresent(e) ? JSON.parse(e) : {};
341
+ const e = r.get(o.UTM);
342
+ return g.isPresent(e) ? JSON.parse(e) : {};
291
343
  }
292
- static createSession() {
293
- s.exists(c.SESSION) || s.set(
294
- c.SESSION,
295
- h.guid(),
296
- n.SESSION_EXPIRY_DAYS * 24 * 60
297
- ), s.setUtms();
344
+ static createSession(e = !1) {
345
+ (e || !r.exists(o.SESSION)) && r.set(
346
+ o.SESSION,
347
+ g.guid(),
348
+ a.SESSION_EXPIRY_DAYS * 24 * 60
349
+ ), r.setUtms();
298
350
  }
299
351
  }
300
- class D {
352
+ class m {
353
+ /**
354
+ * Checks if the current browser is a bot or automated browser
355
+ * @returns true if bot is detected, false otherwise
356
+ */
357
+ static isBot() {
358
+ var i;
359
+ if (typeof window > "u" || typeof navigator > "u")
360
+ return !1;
361
+ if (navigator.webdriver === !0)
362
+ return n.debug("[CPIX] Bot detected: navigator.webdriver is true"), !0;
363
+ const e = ((i = navigator.userAgent) == null ? void 0 : i.toLowerCase()) || "";
364
+ return this.BOT_USER_AGENTS.some(
365
+ (s) => e.includes(s.toLowerCase())
366
+ ) ? (n.debug("[CPIX] Bot detected: User agent matches bot pattern"), !0) : this.hasMissingBrowserFeatures() ? (n.debug("[CPIX] Bot detected: Missing browser features"), !0) : this.isHeadlessBrowser() ? (n.debug("[CPIX] Bot detected: Headless browser indicators"), !0) : !1;
367
+ }
368
+ /**
369
+ * Checks for missing browser features that indicate automation
370
+ * This is a conservative check to avoid false positives
371
+ */
372
+ static hasMissingBrowserFeatures() {
373
+ const e = typeof navigator.plugins > "u" || navigator.plugins.length === 0, t = typeof navigator.languages > "u" || navigator.languages.length === 0;
374
+ return !!(e && t);
375
+ }
376
+ /**
377
+ * Checks for headless browser indicators
378
+ */
379
+ static isHeadlessBrowser() {
380
+ var e, t;
381
+ return (e = navigator.userAgent) != null && e.includes("HeadlessChrome") || window.outerWidth === 0 && window.outerHeight === 0 && window.innerWidth === 0 && window.innerHeight === 0 && // Additional check: if screen dimensions are also zero, it's likely headless
382
+ (screen.width === 0 || screen.height === 0) ? !0 : (typeof navigator.permissions > "u" && ((t = navigator.userAgent) != null && t.includes("Chrome")), !1);
383
+ }
384
+ }
385
+ /**
386
+ * Known bot user agent patterns
387
+ */
388
+ u(m, "BOT_USER_AGENTS", [
389
+ "googlebot",
390
+ "bingbot",
391
+ "slurp",
392
+ "duckduckbot",
393
+ "baiduspider",
394
+ "yandexbot",
395
+ "sogou",
396
+ "exabot",
397
+ "facebot",
398
+ "ia_archiver",
399
+ "siteauditbot",
400
+ "semrushbot",
401
+ "ahrefsbot",
402
+ "mj12bot",
403
+ "dotbot",
404
+ "megaindex",
405
+ "blexbot",
406
+ "petalbot",
407
+ "applebot",
408
+ "crawler",
409
+ "spider",
410
+ "scraper",
411
+ "headless",
412
+ "phantom",
413
+ "selenium",
414
+ "webdriver",
415
+ "puppeteer",
416
+ "playwright",
417
+ "chromium",
418
+ "chrome-lighthouse"
419
+ ]);
420
+ class N {
301
421
  constructor() {
302
- o(this, "instances", []);
303
- o(this, "initialized", !1);
304
- o(this, "sessionCreated", !1);
305
- o(this, "accessToken", "");
306
- o(this, "metaParameters", {});
307
- o(this, "queue");
422
+ u(this, "instances", []);
423
+ u(this, "initialized", !1);
424
+ u(this, "sessionCreated", !1);
425
+ u(this, "accessToken", "");
426
+ u(this, "metaParameters", {});
427
+ u(this, "queue");
428
+ u(this, "isBot", !1);
308
429
  if (!window)
309
430
  throw new Error(
310
431
  "[CPIX] CarterAnalytics SDK can only be used in a browser environment"
311
432
  );
312
- this.queue = new O({
313
- maxRetries: n.QUEUE_MAX_RETRIES,
314
- initialDelay: n.QUEUE_INITIAL_DELAY,
433
+ this.queue = new k({
434
+ maxRetries: a.QUEUE_MAX_RETRIES,
435
+ initialDelay: a.QUEUE_INITIAL_DELAY,
315
436
  consumerHandler: this.publishEventToServer.bind(this)
316
437
  });
317
438
  }
@@ -324,17 +445,55 @@ class D {
324
445
  throw new Error(
325
446
  "[CPIX] At least one instance configuration is required for initialization"
326
447
  );
327
- if (this.instances = e, n.DEBUG = this.instances[0].options.debug === !0, n.API_URL = this.instances[0].options.tracker_server_url, n.USER_PROPERTIES = this.instances[0].options.user_properties || {}, n.SESSION_EXPIRY_DAYS = this.instances[0].options.session_expiry_days || 14, n.COMMON_PROPERTIES = this.instances[0].options.common_properties || {}, s.exists(c.SESSION) || (s.createSession(), this.sessionCreated = !0), s.exists(c.META_PARAMETERS) || await this.generateMetaParameters().then((t) => {
328
- this.metaParameters = t, s.set("metaParameters", JSON.stringify(t), 60 * 24);
329
- }), s.setUtms(), this.metaParameters = JSON.parse(s.get("metaParameters")), this.initialized)
448
+ if (this.isBot = m.isBot(), this.isBot) {
449
+ n.debug(
450
+ "[CPIX] Bot detected - SDK will not track events for this session"
451
+ ), this.instances = e, a.DEBUG = this.instances[0].options.debug === !0, this.initialized = !0;
452
+ return;
453
+ }
454
+ this.instances = e, a.DEBUG = this.instances[0].options.debug === !0, a.API_URL = this.instances[0].options.tracker_server_url, a.USER_PROPERTIES = this.instances[0].options.user_properties || {}, a.SESSION_EXPIRY_DAYS = this.instances[0].options.session_expiry_days || 14, a.COMMON_PROPERTIES = this.instances[0].options.common_properties || {}, r.exists(o.SESSION) || (r.createSession(), this.sessionCreated = !0);
455
+ const t = r.get(o.SESSION);
456
+ if (!r.exists(o.META_PARAMETERS))
457
+ this.metaParameters = await this.generateMetaParameters(), r.set(
458
+ o.META_PARAMETERS,
459
+ JSON.stringify(this.metaParameters),
460
+ 60 * 24
461
+ );
462
+ else {
463
+ const i = r.get(o.META_PARAMETERS);
464
+ if (i)
465
+ try {
466
+ const s = JSON.parse(i);
467
+ s.session !== t ? (n.debug(
468
+ "Session ID mismatch detected, regenerating meta parameters"
469
+ ), this.metaParameters = await this.generateMetaParameters(), r.set(
470
+ o.META_PARAMETERS,
471
+ JSON.stringify(this.metaParameters),
472
+ 60 * 24
473
+ )) : this.metaParameters = s;
474
+ } catch (s) {
475
+ n.error("Failed to parse meta parameters, regenerating:", s), this.metaParameters = await this.generateMetaParameters(), r.set(
476
+ o.META_PARAMETERS,
477
+ JSON.stringify(this.metaParameters),
478
+ 60 * 24
479
+ );
480
+ }
481
+ else
482
+ this.metaParameters = await this.generateMetaParameters(), r.set(
483
+ o.META_PARAMETERS,
484
+ JSON.stringify(this.metaParameters),
485
+ 60 * 24
486
+ );
487
+ }
488
+ if (r.setUtms(), this.initialized)
330
489
  throw new Error(
331
490
  "[CPIX] CarterAnalytics SDK has already been initialized"
332
491
  );
333
492
  if (!this.metaParameters)
334
493
  throw new Error("[CPIX] Meta parameters have not been generated");
335
- s.exists(c.ACCESS_TOKEN) || (this.accessToken = await d.aquireAccessToken(
494
+ r.exists(o.ACCESS_TOKEN) || (this.accessToken = await d.aquireAccessToken(
336
495
  this.instances[0].client_id
337
- ), s.set(c.ACCESS_TOKEN, this.accessToken, 60 * 4)), this.initialized = !0, u.debug("CPIX Initialized"), u.debug(
496
+ ), r.set(o.ACCESS_TOKEN, this.accessToken, 60 * 4)), this.initialized = !0, n.debug("CPIX Initialized"), n.debug(
338
497
  "Carter Analytics SDK initialized with options:",
339
498
  this.instances
340
499
  ), this.sessionCreated && this.publishInit(), this.attachHistoryListener();
@@ -342,7 +501,7 @@ class D {
342
501
  publishInit() {
343
502
  this.publish({
344
503
  event: "init",
345
- user_properties: n.USER_PROPERTIES,
504
+ user_properties: a.USER_PROPERTIES,
346
505
  ...this.metaParameters
347
506
  });
348
507
  }
@@ -358,14 +517,14 @@ class D {
358
517
  page: window.location.pathname,
359
518
  url: window.location.href
360
519
  },
361
- user_properties: n.USER_PROPERTIES,
520
+ user_properties: a.USER_PROPERTIES,
362
521
  ...this.metaParameters
363
522
  });
364
523
  };
365
- history.pushState = (...r) => {
366
- e.apply(history, r), i();
367
- }, history.replaceState = (...r) => {
368
- t.apply(history, r), i();
524
+ history.pushState = (...s) => {
525
+ e.apply(history, s), i();
526
+ }, history.replaceState = (...s) => {
527
+ t.apply(history, s), i();
369
528
  }, window.addEventListener("popstate", i), i();
370
529
  }
371
530
  /**
@@ -377,17 +536,31 @@ class D {
377
536
  throw new Error(
378
537
  "[CPIX] CarterAnalytics SDK has not been initialized. Please initialize before publishing events."
379
538
  );
539
+ if (this.isBot || m.isBot()) {
540
+ n.debug("[CPIX] Event publishing blocked - bot detected");
541
+ return;
542
+ }
380
543
  const t = {
381
544
  ...e,
382
545
  ...this.metaParameters
383
546
  };
384
- t.utm_params = s.getUtms(), document.referrer && (t.referrer = encodeURIComponent(document.referrer)), u.debug("Publishing event:", t), this.queue.publish(t), e.event === "logout" && (s.delete(c.SESSION), s.delete(c.META_PARAMETERS), s.createSession(), this.generateMetaParameters().then((i) => {
385
- this.metaParameters = i, s.set(
386
- c.META_PARAMETERS,
387
- JSON.stringify(this.metaParameters),
388
- 60 * 24
389
- ), this.publishInit();
390
- }));
547
+ if (t.utm_params = r.getUtms(), document.referrer && (t.referrer = encodeURIComponent(document.referrer)), n.debug("Publishing event:", t), this.queue.publish(t), e.event === "logout") {
548
+ r.delete(o.SESSION), r.delete(o.META_PARAMETERS), r.createSession(!0);
549
+ const i = r.get(o.SESSION);
550
+ if (!i) {
551
+ n.error("[CPIX] Failed to create new session on logout");
552
+ return;
553
+ }
554
+ this.generateMetaParameters().then((s) => {
555
+ s.session !== i && (n.error(
556
+ "[CPIX] Session ID mismatch after logout, updating meta parameters"
557
+ ), s.session = i), this.metaParameters = s, r.set(
558
+ o.META_PARAMETERS,
559
+ JSON.stringify(this.metaParameters),
560
+ 60 * 24
561
+ ), this.publishInit();
562
+ });
563
+ }
391
564
  }
392
565
  /**
393
566
  * Generates meta parameters that is attached to every event before publishing.
@@ -400,7 +573,7 @@ class D {
400
573
  const e = await d.getDeviceNetworkParameters();
401
574
  return {
402
575
  client_id: this.instances[0].client_id,
403
- session: s.get(c.SESSION),
576
+ session: r.get(o.SESSION),
404
577
  location: {
405
578
  city: e.city,
406
579
  region: e.region,
@@ -413,7 +586,14 @@ class D {
413
586
  brand: d.getDeviceManufacturer(),
414
587
  ip_address: e.ip_address,
415
588
  platform: d.getDevicePlatform(),
416
- cpix_sdk_version: n.version
589
+ browser_name: d.getBrowserName(),
590
+ browser_version: d.getBrowserVersion(),
591
+ screen_resolution: d.getScreenResolution(),
592
+ viewport_size: d.getViewportSize(),
593
+ language: d.getLanguage(),
594
+ os_version: d.getOSVersion(),
595
+ user_agent: d.getUserAgent(),
596
+ cpix_sdk_version: a.version
417
597
  },
418
598
  referrer: encodeURIComponent(document.referrer)
419
599
  };
@@ -426,29 +606,29 @@ class D {
426
606
  try {
427
607
  e.timestamp = Date.now(), e.event_properties = {
428
608
  url: window.location.href,
429
- ...n.COMMON_PROPERTIES,
609
+ ...a.COMMON_PROPERTIES,
430
610
  ...e.event_properties
431
- }, e.device && (e.device.cpix_sdk_version = n.version);
432
- const t = await fetch(`${n.API_URL}/api/event`, {
611
+ }, e.device && (e.device.cpix_sdk_version = a.version);
612
+ const t = await fetch(`${a.API_URL}/api/event`, {
433
613
  method: "POST",
434
614
  body: JSON.stringify({ event_data: e }),
435
615
  headers: {
436
616
  "Content-Type": "application/json",
437
- Authorization: `Bearer ${s.get(c.ACCESS_TOKEN)}`
617
+ Authorization: `Bearer ${r.get(o.ACCESS_TOKEN)}`
438
618
  }
439
619
  });
440
620
  if (!t.ok)
441
621
  throw t.status === 401 && (this.accessToken = await d.aquireAccessToken(
442
622
  this.instances[0].client_id
443
- ), s.set(c.ACCESS_TOKEN, this.accessToken, 60 * 4)), new Error("[CPIX] Failed to publish event");
444
- u.debug("Event published:", t.ok);
623
+ ), r.set(o.ACCESS_TOKEN, this.accessToken, 60 * 4)), new Error("[CPIX] Failed to publish event");
624
+ n.debug("Event published:", t.ok);
445
625
  } catch (t) {
446
- throw u.error("Failed to publish event:", t), new Error("[CPIX] Failed to publish event");
626
+ throw n.error("Failed to publish event:", t), new Error("[CPIX] Failed to publish event");
447
627
  }
448
628
  }
449
629
  }
450
- const N = new D();
451
- typeof window < "u" && (window.cpix = N);
630
+ const O = new N();
631
+ typeof window < "u" && (window.cpix = O);
452
632
  export {
453
- N as CarterAnalytics
633
+ O as CarterAnalytics
454
634
  };
package/dist/cpix.umd.cjs CHANGED
@@ -1 +1 @@
1
- (function(l,d){typeof exports=="object"&&typeof module<"u"?d(exports):typeof define=="function"&&define.amd?define(["exports"],d):(l=typeof globalThis<"u"?globalThis:l||self,d(l.tracker={}))})(this,function(l){"use strict";var T=Object.defineProperty;var b=(l,d,p)=>d in l?T(l,d,{enumerable:!0,configurable:!0,writable:!0,value:p}):l[d]=p;var u=(l,d,p)=>(b(l,typeof d!="symbol"?d+"":d,p),p);const E={name:"@carter-rmn/cpix-js",version:"1.0.5",type:"module",files:["dist"],main:"dist/cpix.umd.cjs",module:"dist/cpix.js",types:"dist/cpix.d.ts",exports:{".":{import:"./dist/cpix.js",require:"./dist/cpix.umd.cjs"}},scripts:{dev:"vite",build:"tsc && vite build",preview:"vite preview"},devDependencies:{picocolors:"^1.0.0","rollup-plugin-visualizer":"^5.12.0",typescript:"^5.2.2",vite:"^5.2.0","vite-plugin-progress":"^0.0.7"},dependencies:{"vite-plugin-dts":"^3.8.1"}},r={DEBUG:!1,TRACKER_FUNC_NAME:"cpix",API_URL:"",QUEUE_MAX_RETRIES:3,QUEUE_INITIAL_DELAY:1e4,version:E.version,package:E.name,USER_PROPERTIES:{},SESSION_EXPIRY_DAYS:14,COMMON_PROPERTIES:{}},a={SESSION:"cpix_session",META_PARAMETERS:"cpix_meta_parameters",ACCESS_TOKEN:"cpix_access_token",UTM:"cpix_utm"},P=["utm_source","utm_medium","utm_term","utm_content","utm_campaign"],o=function(){const f=()=>r.DEBUG;return{info:function(...e){console.log(...e)},debug:function(...e){f()&&console.log(...e)},error:function(...e){console.error(...e)}}}();class _ extends EventTarget{constructor(t={maxRetries:3,initialDelay:1e4,consumerHandler:i=>(o.debug("Consuming event:",i),Promise.resolve())}){super();u(this,"dataQueue");u(this,"retryQueue");u(this,"maxRetries");u(this,"initialDelay");u(this,"publishEvent");u(this,"retryEvent");u(this,"handler");this.dataQueue=[],this.retryQueue=[],this.maxRetries=t.maxRetries,this.initialDelay=t.initialDelay,this.handler=t.consumerHandler,this.publishEvent=new Event("eventPublished"),this.retryEvent=new Event("retryMessage"),this.consume(),this.retry()}publish(t){o.debug("publishing event");const i={data:t,id:`${Date.now()+Math.random()}`,retryCount:0,retryDelay:this.initialDelay};this.dataQueue.push(i),this.dispatchEvent(this.publishEvent)}consume(){o.debug("Started Consumer Queue"),this.addEventListener("eventPublished",async()=>{for(;this.dataQueue.length>0;){const t=this.dataQueue.shift(),{data:i={}}=t;try{await this.handler(i),this.acknowledge(t==null?void 0:t.id)}catch(n){o.error("Failed to publish event:",n),this.scheduleRetry(t)}}})}scheduleRetry(t){if(t.retryCount>=this.maxRetries){o.error("Max retries reached for message:",t);return}setTimeout(()=>{this.retryQueue.push({...t,retryCount:t.retryCount+1,retryDelay:t.retryDelay*2}),this.dispatchEvent(this.retryEvent)},t.retryDelay)}acknowledge(t){this.dataQueue=this.dataQueue.filter(i=>i.id!==t)}retry(){o.debug("Started Retry Queue"),this.addEventListener("retryMessage",async()=>{for(;this.retryQueue.length>0;){const t=this.retryQueue.shift(),{data:i={}}=t;try{await this.handler(i),this.acknowledge(t==null?void 0:t.id)}catch(n){o.error("Failed to publish event:",n),this.scheduleRetry(t)}}})}}class m{static getBrowserInfo(){var n,c,g,S,v;const e=navigator.userAgent||"";let t,i;return/chrome/i.test(e)?(t="Chrome",i=(n=e.match(/chrome\/(\d+)/i))==null?void 0:n[1]):/firefox/i.test(e)?(t="Firefox",i=(c=e.match(/firefox\/(\d+)/i))==null?void 0:c[1]):/safari/i.test(e)?(t="Safari",i=(g=e.match(/version\/(\d+)/i))==null?void 0:g[1]):/edge/i.test(e)?(t="Edge",i=(S=e.match(/edge\/(\d+)/i))==null?void 0:S[1]):/trident/i.test(e)?(t="Internet Explorer",i=(v=e.match(/rv:(\d+)/i))==null?void 0:v[1]):(t="Unknown",i="Unknown"),`${t} ${i}`}static getDeviceCategory(){const e=navigator.userAgent;return/mobile/i.test(e)?"Mobile":/tablet/i.test(e)?"Tablet":"Desktop"}static getDevicePlatform(){const e=navigator.userAgent;return/android/i.test(e)?"Android":/iphone|ipad|ipod/i.test(e)?"iOS":/windows phone/i.test(e)?"Windows Phone":/mac|Macintosh/i.test(e)?"Mac":/windows|Microsoft/i.test(e)?"Windows":/linux/i.test(e)?"Linux":"Unknown"}static getDeviceManufacturer(){const e=navigator.userAgent;let t;return/iphone|ipad|ipod|mac|Macintosh/i.test(e)?t="Apple":/samsung/i.test(e)?t="Samsung":/google/i.test(e)?t="Google":/huawei/i.test(e)?t="Huawei":/xiaomi/i.test(e)?t="Xiaomi":/oneplus/i.test(e)?t="OnePlus":/dell/i.test(e)?t="Dell":/lenovo/i.test(e)?t="Lenovo":/acer/i.test(e)?t="Acer":/asus/i.test(e)?t="Asus":/toshiba/i.test(e)?t="Toshiba":t="Unknown",t}static async getDeviceNetworkParameters(){try{const e=await fetch(`${r.API_URL}/api/geolocation`),{data:t}=await e.json();return{city:t.city||"Unknown",region:t.region||"Unknown",country:t.country||"Unknown",timezone:t.timezone||"Unknown",loc:t.loc||"Unknown",ip_address:t.ip_address||"Unknown"}}catch(e){return o.error("Error retrieving device network parameters:",e),{city:"Unknown",region:"Unknown",country:"Unknown",timezone:"Unknown",loc:"Unknown",ip_address:"Unknown"}}}static async aquireAccessToken(e){try{return(await(await fetch(`${r.API_URL}/api/authenticate`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({accountId:e,metadata:{sdk:r.package,version:r.version,hostname:window.location.hostname}})})).json()).accessToken}catch(t){throw o.error("Error acquiring access token:",t),new Error("[CPIX] Authentication error")}}}class h{static isPresent(e){return typeof e<"u"&&e!==null&&e!==""}static now(){return 1*new Date().getTime()}static guid(){return E.version+"-xxxxxxxx-".replace(/[x]/g,function(e){const t=Math.random()*36|0;return(e=="x"?t:t&3|8).toString(36)})+(1*new Date().getTime()).toString(36)}static optionalData(e){return h.isPresent(e)===!1?"":typeof e=="object"?h.optionalData(JSON.stringify(e)):typeof e=="function"?h.optionalData(e()):String(e)}static sleep(e){return new Promise(t=>setTimeout(t,e))}}class w{static getParametersByName(e,t){t||(t=window.location.href),e=e.replace(/[[\]]/g,"\\$&");const i=new RegExp("[?&]"+e+"(=([^&#]*)|&|#|$)","gi"),n=[];let c;for(;(c=i.exec(t))!==null;)c[2]&&n.push(decodeURIComponent(c[2].replace(/\+/g," ")));return n.length>0?n:null}static externalHost(e){var t;return e.hostname!=location.hostname&&((t=e==null?void 0:e.protocol)==null?void 0:t.indexOf("http"))===0}}class s{static prefix(){return`__${r.TRACKER_FUNC_NAME}__`}static get(e){const t=`${s.prefix()}${e}`,i=document.cookie.split("; ").find(n=>n.startsWith(`${t}=`));return i?i.split("=")[1]:void 0}static set(e,t,i){const n=`${s.prefix()}${e}`,c=new Date;c.setTime(c.getTime()+i*60*1e3),document.cookie=`${n}=${t}; expires=${c.toUTCString()}; path=/`}static delete(e){const t=`${s.prefix()}${e}`;document.cookie=`${t}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/`}static clear(){document.cookie.split("; ").filter(e=>e.startsWith(s.prefix())).forEach(e=>{const t=e.split("=")[0];document.cookie=`${t}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/`})}static exists(e){return!!s.get(e)}static setUtms(){const e=P;let t=!1;for(let i=0;i<e.length;i++){const n=e[i];if(h.isPresent(w.getParametersByName(n,window.location.href))){t=!0;break}}if(t){let i;const n=[];for(let c=0;c<e.length;c++){const g=e[c];i=w.getParametersByName(g,window.location.href),n.push({[g]:encodeURIComponent(i)})}s.set(a.UTM,JSON.stringify(n),r.SESSION_EXPIRY_DAYS*24*60)}}static getUtms(){const e=s.get(a.UTM);return h.isPresent(e)?JSON.parse(e):{}}static createSession(){s.exists(a.SESSION)||s.set(a.SESSION,h.guid(),r.SESSION_EXPIRY_DAYS*24*60),s.setUtms()}}class x{constructor(){u(this,"instances",[]);u(this,"initialized",!1);u(this,"sessionCreated",!1);u(this,"accessToken","");u(this,"metaParameters",{});u(this,"queue");if(!window)throw new Error("[CPIX] CarterAnalytics SDK can only be used in a browser environment");this.queue=new _({maxRetries:r.QUEUE_MAX_RETRIES,initialDelay:r.QUEUE_INITIAL_DELAY,consumerHandler:this.publishEventToServer.bind(this)})}async initialize(e){if(!e||e.length===0)throw new Error("[CPIX] At least one instance configuration is required for initialization");if(this.instances=e,r.DEBUG=this.instances[0].options.debug===!0,r.API_URL=this.instances[0].options.tracker_server_url,r.USER_PROPERTIES=this.instances[0].options.user_properties||{},r.SESSION_EXPIRY_DAYS=this.instances[0].options.session_expiry_days||14,r.COMMON_PROPERTIES=this.instances[0].options.common_properties||{},s.exists(a.SESSION)||(s.createSession(),this.sessionCreated=!0),s.exists(a.META_PARAMETERS)||await this.generateMetaParameters().then(t=>{this.metaParameters=t,s.set("metaParameters",JSON.stringify(t),60*24)}),s.setUtms(),this.metaParameters=JSON.parse(s.get("metaParameters")),this.initialized)throw new Error("[CPIX] CarterAnalytics SDK has already been initialized");if(!this.metaParameters)throw new Error("[CPIX] Meta parameters have not been generated");s.exists(a.ACCESS_TOKEN)||(this.accessToken=await m.aquireAccessToken(this.instances[0].client_id),s.set(a.ACCESS_TOKEN,this.accessToken,60*4)),this.initialized=!0,o.debug("CPIX Initialized"),o.debug("Carter Analytics SDK initialized with options:",this.instances),this.sessionCreated&&this.publishInit(),this.attachHistoryListener()}publishInit(){this.publish({event:"init",user_properties:r.USER_PROPERTIES,...this.metaParameters})}attachHistoryListener(){const e=history.pushState,t=history.replaceState,i=()=>{this.publish({event:"page_view",event_properties:{title:document.title,page:window.location.pathname,url:window.location.href},user_properties:r.USER_PROPERTIES,...this.metaParameters})};history.pushState=(...n)=>{e.apply(history,n),i()},history.replaceState=(...n)=>{t.apply(history,n),i()},window.addEventListener("popstate",i),i()}publish(e){if(!this.initialized)throw new Error("[CPIX] CarterAnalytics SDK has not been initialized. Please initialize before publishing events.");const t={...e,...this.metaParameters};t.utm_params=s.getUtms(),document.referrer&&(t.referrer=encodeURIComponent(document.referrer)),o.debug("Publishing event:",t),this.queue.publish(t),e.event==="logout"&&(s.delete(a.SESSION),s.delete(a.META_PARAMETERS),s.createSession(),this.generateMetaParameters().then(i=>{this.metaParameters=i,s.set(a.META_PARAMETERS,JSON.stringify(this.metaParameters),60*24),this.publishInit()}))}async generateMetaParameters(){if(!window)throw new Error("[CPIX] Meta parameters can only be generated in a browser environment");const e=await m.getDeviceNetworkParameters();return{client_id:this.instances[0].client_id,session:s.get(a.SESSION),location:{city:e.city,region:e.region,loc:e.loc,timezone:e.timezone,country:e.country},device:{category:m.getDeviceCategory(),brand:m.getDeviceManufacturer(),ip_address:e.ip_address,platform:m.getDevicePlatform(),cpix_sdk_version:r.version},referrer:encodeURIComponent(document.referrer)}}async publishEventToServer(e){try{e.timestamp=Date.now(),e.event_properties={url:window.location.href,...r.COMMON_PROPERTIES,...e.event_properties},e.device&&(e.device.cpix_sdk_version=r.version);const t=await fetch(`${r.API_URL}/api/event`,{method:"POST",body:JSON.stringify({event_data:e}),headers:{"Content-Type":"application/json",Authorization:`Bearer ${s.get(a.ACCESS_TOKEN)}`}});if(!t.ok)throw t.status===401&&(this.accessToken=await m.aquireAccessToken(this.instances[0].client_id),s.set(a.ACCESS_TOKEN,this.accessToken,60*4)),new Error("[CPIX] Failed to publish event");o.debug("Event published:",t.ok)}catch(t){throw o.error("Failed to publish event:",t),new Error("[CPIX] Failed to publish event")}}}const y=new x;typeof window<"u"&&(window.cpix=y),l.CarterAnalytics=y,Object.defineProperty(l,Symbol.toStringTag,{value:"Module"})});
1
+ (function(l,h){typeof exports=="object"&&typeof module<"u"?h(exports):typeof define=="function"&&define.amd?define(["exports"],h):(l=typeof globalThis<"u"?globalThis:l||self,h(l.tracker={}))})(this,function(l){"use strict";var x=Object.defineProperty;var T=(l,h,f)=>h in l?x(l,h,{enumerable:!0,configurable:!0,writable:!0,value:f}):l[h]=f;var u=(l,h,f)=>(T(l,typeof h!="symbol"?h+"":h,f),f);const E={name:"@carter-rmn/cpix-js",version:"1.0.8",type:"module",files:["dist"],main:"dist/cpix.umd.cjs",module:"dist/cpix.js",types:"dist/cpix.d.ts",exports:{".":{import:"./dist/cpix.js",require:"./dist/cpix.umd.cjs"}},scripts:{dev:"vite",build:"tsc && vite build",preview:"vite preview"},devDependencies:{picocolors:"^1.0.0","rollup-plugin-visualizer":"^5.12.0",typescript:"^5.2.2",vite:"^5.2.0","vite-plugin-progress":"^0.0.7"},dependencies:{"vite-plugin-dts":"^3.8.1"}},o={DEBUG:!1,TRACKER_FUNC_NAME:"cpix",API_URL:"",QUEUE_MAX_RETRIES:3,QUEUE_INITIAL_DELAY:1e4,version:E.version,package:E.name,USER_PROPERTIES:{},SESSION_EXPIRY_DAYS:14,COMMON_PROPERTIES:{}},a={SESSION:"cpix_session",META_PARAMETERS:"cpix_meta_parameters",ACCESS_TOKEN:"cpix_access_token",UTM:"cpix_utm"},P=["utm_source","utm_medium","utm_term","utm_content","utm_campaign"],r=function(){const m=()=>o.DEBUG;return{info:function(...e){console.log(...e)},debug:function(...e){m()&&console.log(...e)},error:function(...e){console.error(...e)}}}();class A extends EventTarget{constructor(t={maxRetries:3,initialDelay:1e4,consumerHandler:i=>(r.debug("Consuming event:",i),Promise.resolve())}){super();u(this,"dataQueue");u(this,"retryQueue");u(this,"maxRetries");u(this,"initialDelay");u(this,"publishEvent");u(this,"retryEvent");u(this,"handler");this.dataQueue=[],this.retryQueue=[],this.maxRetries=t.maxRetries,this.initialDelay=t.initialDelay,this.handler=t.consumerHandler,this.publishEvent=new Event("eventPublished"),this.retryEvent=new Event("retryMessage"),this.consume(),this.retry()}publish(t){r.debug("publishing event");const i={data:t,id:`${Date.now()+Math.random()}`,retryCount:0,retryDelay:this.initialDelay};this.dataQueue.push(i),this.dispatchEvent(this.publishEvent)}consume(){r.debug("Started Consumer Queue"),this.addEventListener("eventPublished",async()=>{for(;this.dataQueue.length>0;){const t=this.dataQueue.shift(),{data:i={}}=t;try{await this.handler(i),this.acknowledge(t==null?void 0:t.id)}catch(s){r.error("Failed to publish event:",s),this.scheduleRetry(t)}}})}scheduleRetry(t){if(t.retryCount>=this.maxRetries){r.error("Max retries reached for message:",t);return}setTimeout(()=>{this.retryQueue.push({...t,retryCount:t.retryCount+1,retryDelay:t.retryDelay*2}),this.dispatchEvent(this.retryEvent)},t.retryDelay)}acknowledge(t){this.dataQueue=this.dataQueue.filter(i=>i.id!==t)}retry(){r.debug("Started Retry Queue"),this.addEventListener("retryMessage",async()=>{for(;this.retryQueue.length>0;){const t=this.retryQueue.shift(),{data:i={}}=t;try{await this.handler(i),this.acknowledge(t==null?void 0:t.id)}catch(s){r.error("Failed to publish event:",s),this.scheduleRetry(t)}}})}}class d{static getBrowserInfo(){var s,c,g,w,b;const e=navigator.userAgent||"";let t,i;return/chrome/i.test(e)?(t="Chrome",i=(s=e.match(/chrome\/(\d+)/i))==null?void 0:s[1]):/firefox/i.test(e)?(t="Firefox",i=(c=e.match(/firefox\/(\d+)/i))==null?void 0:c[1]):/safari/i.test(e)?(t="Safari",i=(g=e.match(/version\/(\d+)/i))==null?void 0:g[1]):/edge/i.test(e)?(t="Edge",i=(w=e.match(/edge\/(\d+)/i))==null?void 0:w[1]):/trident/i.test(e)?(t="Internet Explorer",i=(b=e.match(/rv:(\d+)/i))==null?void 0:b[1]):(t="Unknown",i="Unknown"),`${t} ${i}`}static getBrowserName(){const e=navigator.userAgent||"";let t;return/chrome/i.test(e)&&!/edge/i.test(e)?t="Chrome":/firefox/i.test(e)?t="Firefox":/safari/i.test(e)&&!/chrome/i.test(e)?t="Safari":/edge/i.test(e)?t="Edge":/trident/i.test(e)?t="Internet Explorer":t="Unknown",t}static getBrowserVersion(){var i,s,c,g,w;const e=navigator.userAgent||"";let t;return/chrome/i.test(e)&&!/edge/i.test(e)?t=((i=e.match(/chrome\/(\d+)/i))==null?void 0:i[1])||"Unknown":/firefox/i.test(e)?t=((s=e.match(/firefox\/(\d+)/i))==null?void 0:s[1])||"Unknown":/safari/i.test(e)&&!/chrome/i.test(e)?t=((c=e.match(/version\/(\d+)/i))==null?void 0:c[1])||"Unknown":/edge/i.test(e)?t=((g=e.match(/edge\/(\d+)/i))==null?void 0:g[1])||"Unknown":/trident/i.test(e)?t=((w=e.match(/rv:(\d+)/i))==null?void 0:w[1])||"Unknown":t="Unknown",t}static getScreenResolution(){return typeof window>"u"||!window.screen?"Unknown":`${window.screen.width}x${window.screen.height}`}static getViewportSize(){return typeof window>"u"?"Unknown":`${window.innerWidth}x${window.innerHeight}`}static getLanguage(){var e;return typeof navigator>"u"?"Unknown":navigator.language||((e=navigator.languages)==null?void 0:e[0])||"Unknown"}static getOSVersion(){const e=navigator.userAgent||"";let t="Unknown";if(/iphone|ipad|ipod/i.test(e)){const i=e.match(/os (\d+[._]\d+)/i);i&&(t=i[1].replace("_","."))}else if(/android/i.test(e)){const i=e.match(/android (\d+(\.\d+)?)/i);i&&(t=i[1])}else if(/windows/i.test(e))if(/windows nt 10.0/i.test(e))t="10";else if(/windows nt 6.3/i.test(e))t="8.1";else if(/windows nt 6.2/i.test(e))t="8";else if(/windows nt 6.1/i.test(e))t="7";else{const i=e.match(/windows nt (\d+\.\d+)/i);i&&(t=i[1])}else if(/mac|Macintosh/i.test(e)){const i=e.match(/mac os x (\d+[._]\d+)/i);i&&(t=i[1].replace("_","."))}return t}static getUserAgent(){return typeof navigator>"u"||!navigator.userAgent?"Unknown":navigator.userAgent}static getDeviceCategory(){const e=navigator.userAgent;return/mobile/i.test(e)?"Mobile":/tablet/i.test(e)?"Tablet":"Desktop"}static getDevicePlatform(){const e=navigator.userAgent;return/android/i.test(e)?"Android":/iphone|ipad|ipod/i.test(e)?"iOS":/windows phone/i.test(e)?"Windows Phone":/mac|Macintosh/i.test(e)?"Mac":/windows|Microsoft/i.test(e)?"Windows":/linux/i.test(e)?"Linux":"Unknown"}static getDeviceManufacturer(){const e=navigator.userAgent;let t;return/iphone|ipad|ipod|mac|Macintosh/i.test(e)?t="Apple":/samsung/i.test(e)?t="Samsung":/google/i.test(e)?t="Google":/huawei/i.test(e)?t="Huawei":/xiaomi/i.test(e)?t="Xiaomi":/oneplus/i.test(e)?t="OnePlus":/dell/i.test(e)?t="Dell":/lenovo/i.test(e)?t="Lenovo":/acer/i.test(e)?t="Acer":/asus/i.test(e)?t="Asus":/toshiba/i.test(e)?t="Toshiba":t="Unknown",t}static async getDeviceNetworkParameters(){try{const e=await fetch(`${o.API_URL}/api/geolocation`),{data:t}=await e.json();return{city:t.city||"Unknown",region:t.region||"Unknown",country:t.country||"Unknown",timezone:t.timezone||"Unknown",loc:t.loc||"Unknown",ip_address:t.ip_address||"Unknown"}}catch(e){return r.error("Error retrieving device network parameters:",e),{city:"Unknown",region:"Unknown",country:"Unknown",timezone:"Unknown",loc:"Unknown",ip_address:"Unknown"}}}static async aquireAccessToken(e){try{return(await(await fetch(`${o.API_URL}/api/authenticate`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({accountId:e,metadata:{sdk:o.package,version:o.version,hostname:window.location.hostname}})})).json()).accessToken}catch(t){throw r.error("Error acquiring access token:",t),new Error("[CPIX] Authentication error")}}}class p{static isPresent(e){return typeof e<"u"&&e!==null&&e!==""}static now(){return 1*new Date().getTime()}static guid(){return E.version+"-xxxxxxxx-".replace(/[x]/g,function(e){const t=Math.random()*36|0;return(e=="x"?t:t&3|8).toString(36)})+(1*new Date().getTime()).toString(36)}static optionalData(e){return p.isPresent(e)===!1?"":typeof e=="object"?p.optionalData(JSON.stringify(e)):typeof e=="function"?p.optionalData(e()):String(e)}static sleep(e){return new Promise(t=>setTimeout(t,e))}}class v{static getParametersByName(e,t){t||(t=window.location.href),e=e.replace(/[[\]]/g,"\\$&");const i=new RegExp("[?&]"+e+"(=([^&#]*)|&|#|$)","gi"),s=[];let c;for(;(c=i.exec(t))!==null;)c[2]&&s.push(decodeURIComponent(c[2].replace(/\+/g," ")));return s.length>0?s:null}static externalHost(e){var t;return e.hostname!=location.hostname&&((t=e==null?void 0:e.protocol)==null?void 0:t.indexOf("http"))===0}}class n{static prefix(){return`__${o.TRACKER_FUNC_NAME}__`}static get(e){const t=`${n.prefix()}${e}`,i=document.cookie.split("; ").find(s=>s.startsWith(`${t}=`));return i?i.split("=")[1]:void 0}static set(e,t,i){const s=`${n.prefix()}${e}`,c=new Date;c.setTime(c.getTime()+i*60*1e3),document.cookie=`${s}=${t}; expires=${c.toUTCString()}; path=/`}static delete(e){const t=`${n.prefix()}${e}`;document.cookie=`${t}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/`}static clear(){document.cookie.split("; ").filter(e=>e.startsWith(n.prefix())).forEach(e=>{const t=e.split("=")[0];document.cookie=`${t}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/`})}static exists(e){return!!n.get(e)}static setUtms(){const e=P;let t=!1;for(let i=0;i<e.length;i++){const s=e[i];if(p.isPresent(v.getParametersByName(s,window.location.href))){t=!0;break}}if(t){let i;const s=[];for(let c=0;c<e.length;c++){const g=e[c];i=v.getParametersByName(g,window.location.href),s.push({[g]:encodeURIComponent(i)})}n.set(a.UTM,JSON.stringify(s),o.SESSION_EXPIRY_DAYS*24*60)}}static getUtms(){const e=n.get(a.UTM);return p.isPresent(e)?JSON.parse(e):{}}static createSession(e=!1){(e||!n.exists(a.SESSION))&&n.set(a.SESSION,p.guid(),o.SESSION_EXPIRY_DAYS*24*60),n.setUtms()}}class S{static isBot(){var i;if(typeof window>"u"||typeof navigator>"u")return!1;if(navigator.webdriver===!0)return r.debug("[CPIX] Bot detected: navigator.webdriver is true"),!0;const e=((i=navigator.userAgent)==null?void 0:i.toLowerCase())||"";return this.BOT_USER_AGENTS.some(s=>e.includes(s.toLowerCase()))?(r.debug("[CPIX] Bot detected: User agent matches bot pattern"),!0):this.hasMissingBrowserFeatures()?(r.debug("[CPIX] Bot detected: Missing browser features"),!0):this.isHeadlessBrowser()?(r.debug("[CPIX] Bot detected: Headless browser indicators"),!0):!1}static hasMissingBrowserFeatures(){const e=typeof navigator.plugins>"u"||navigator.plugins.length===0,t=typeof navigator.languages>"u"||navigator.languages.length===0;return!!(e&&t)}static isHeadlessBrowser(){var e,t;return(e=navigator.userAgent)!=null&&e.includes("HeadlessChrome")||window.outerWidth===0&&window.outerHeight===0&&window.innerWidth===0&&window.innerHeight===0&&(screen.width===0||screen.height===0)?!0:(typeof navigator.permissions>"u"&&((t=navigator.userAgent)!=null&&t.includes("Chrome")),!1)}}u(S,"BOT_USER_AGENTS",["googlebot","bingbot","slurp","duckduckbot","baiduspider","yandexbot","sogou","exabot","facebot","ia_archiver","siteauditbot","semrushbot","ahrefsbot","mj12bot","dotbot","megaindex","blexbot","petalbot","applebot","crawler","spider","scraper","headless","phantom","selenium","webdriver","puppeteer","playwright","chromium","chrome-lighthouse"]);class _{constructor(){u(this,"instances",[]);u(this,"initialized",!1);u(this,"sessionCreated",!1);u(this,"accessToken","");u(this,"metaParameters",{});u(this,"queue");u(this,"isBot",!1);if(!window)throw new Error("[CPIX] CarterAnalytics SDK can only be used in a browser environment");this.queue=new A({maxRetries:o.QUEUE_MAX_RETRIES,initialDelay:o.QUEUE_INITIAL_DELAY,consumerHandler:this.publishEventToServer.bind(this)})}async initialize(e){if(!e||e.length===0)throw new Error("[CPIX] At least one instance configuration is required for initialization");if(this.isBot=S.isBot(),this.isBot){r.debug("[CPIX] Bot detected - SDK will not track events for this session"),this.instances=e,o.DEBUG=this.instances[0].options.debug===!0,this.initialized=!0;return}this.instances=e,o.DEBUG=this.instances[0].options.debug===!0,o.API_URL=this.instances[0].options.tracker_server_url,o.USER_PROPERTIES=this.instances[0].options.user_properties||{},o.SESSION_EXPIRY_DAYS=this.instances[0].options.session_expiry_days||14,o.COMMON_PROPERTIES=this.instances[0].options.common_properties||{},n.exists(a.SESSION)||(n.createSession(),this.sessionCreated=!0);const t=n.get(a.SESSION);if(!n.exists(a.META_PARAMETERS))this.metaParameters=await this.generateMetaParameters(),n.set(a.META_PARAMETERS,JSON.stringify(this.metaParameters),60*24);else{const i=n.get(a.META_PARAMETERS);if(i)try{const s=JSON.parse(i);s.session!==t?(r.debug("Session ID mismatch detected, regenerating meta parameters"),this.metaParameters=await this.generateMetaParameters(),n.set(a.META_PARAMETERS,JSON.stringify(this.metaParameters),60*24)):this.metaParameters=s}catch(s){r.error("Failed to parse meta parameters, regenerating:",s),this.metaParameters=await this.generateMetaParameters(),n.set(a.META_PARAMETERS,JSON.stringify(this.metaParameters),60*24)}else this.metaParameters=await this.generateMetaParameters(),n.set(a.META_PARAMETERS,JSON.stringify(this.metaParameters),60*24)}if(n.setUtms(),this.initialized)throw new Error("[CPIX] CarterAnalytics SDK has already been initialized");if(!this.metaParameters)throw new Error("[CPIX] Meta parameters have not been generated");n.exists(a.ACCESS_TOKEN)||(this.accessToken=await d.aquireAccessToken(this.instances[0].client_id),n.set(a.ACCESS_TOKEN,this.accessToken,60*4)),this.initialized=!0,r.debug("CPIX Initialized"),r.debug("Carter Analytics SDK initialized with options:",this.instances),this.sessionCreated&&this.publishInit(),this.attachHistoryListener()}publishInit(){this.publish({event:"init",user_properties:o.USER_PROPERTIES,...this.metaParameters})}attachHistoryListener(){const e=history.pushState,t=history.replaceState,i=()=>{this.publish({event:"page_view",event_properties:{title:document.title,page:window.location.pathname,url:window.location.href},user_properties:o.USER_PROPERTIES,...this.metaParameters})};history.pushState=(...s)=>{e.apply(history,s),i()},history.replaceState=(...s)=>{t.apply(history,s),i()},window.addEventListener("popstate",i),i()}publish(e){if(!this.initialized)throw new Error("[CPIX] CarterAnalytics SDK has not been initialized. Please initialize before publishing events.");if(this.isBot||S.isBot()){r.debug("[CPIX] Event publishing blocked - bot detected");return}const t={...e,...this.metaParameters};if(t.utm_params=n.getUtms(),document.referrer&&(t.referrer=encodeURIComponent(document.referrer)),r.debug("Publishing event:",t),this.queue.publish(t),e.event==="logout"){n.delete(a.SESSION),n.delete(a.META_PARAMETERS),n.createSession(!0);const i=n.get(a.SESSION);if(!i){r.error("[CPIX] Failed to create new session on logout");return}this.generateMetaParameters().then(s=>{s.session!==i&&(r.error("[CPIX] Session ID mismatch after logout, updating meta parameters"),s.session=i),this.metaParameters=s,n.set(a.META_PARAMETERS,JSON.stringify(this.metaParameters),60*24),this.publishInit()})}}async generateMetaParameters(){if(!window)throw new Error("[CPIX] Meta parameters can only be generated in a browser environment");const e=await d.getDeviceNetworkParameters();return{client_id:this.instances[0].client_id,session:n.get(a.SESSION),location:{city:e.city,region:e.region,loc:e.loc,timezone:e.timezone,country:e.country},device:{category:d.getDeviceCategory(),brand:d.getDeviceManufacturer(),ip_address:e.ip_address,platform:d.getDevicePlatform(),browser_name:d.getBrowserName(),browser_version:d.getBrowserVersion(),screen_resolution:d.getScreenResolution(),viewport_size:d.getViewportSize(),language:d.getLanguage(),os_version:d.getOSVersion(),user_agent:d.getUserAgent(),cpix_sdk_version:o.version},referrer:encodeURIComponent(document.referrer)}}async publishEventToServer(e){try{e.timestamp=Date.now(),e.event_properties={url:window.location.href,...o.COMMON_PROPERTIES,...e.event_properties},e.device&&(e.device.cpix_sdk_version=o.version);const t=await fetch(`${o.API_URL}/api/event`,{method:"POST",body:JSON.stringify({event_data:e}),headers:{"Content-Type":"application/json",Authorization:`Bearer ${n.get(a.ACCESS_TOKEN)}`}});if(!t.ok)throw t.status===401&&(this.accessToken=await d.aquireAccessToken(this.instances[0].client_id),n.set(a.ACCESS_TOKEN,this.accessToken,60*4)),new Error("[CPIX] Failed to publish event");r.debug("Event published:",t.ok)}catch(t){throw r.error("Failed to publish event:",t),new Error("[CPIX] Failed to publish event")}}}const y=new _;typeof window<"u"&&(window.cpix=y),l.CarterAnalytics=y,Object.defineProperty(l,Symbol.toStringTag,{value:"Module"})});
@@ -10,6 +10,7 @@ declare class CarterAnalytics {
10
10
  private accessToken;
11
11
  private metaParameters;
12
12
  private queue;
13
+ private isBot;
13
14
  constructor();
14
15
  /**
15
16
  * Initializes the CarterAnalytics SDK with the provided configuration options.
@@ -82,6 +82,34 @@ export interface Device {
82
82
  * The platform of the device.
83
83
  */
84
84
  platform: string;
85
+ /**
86
+ * The browser name.
87
+ */
88
+ browser_name?: string;
89
+ /**
90
+ * The browser version.
91
+ */
92
+ browser_version?: string;
93
+ /**
94
+ * The screen resolution (width x height).
95
+ */
96
+ screen_resolution?: string;
97
+ /**
98
+ * The viewport size (width x height).
99
+ */
100
+ viewport_size?: string;
101
+ /**
102
+ * The language of the browser.
103
+ */
104
+ language?: string;
105
+ /**
106
+ * The OS version (if detectable).
107
+ */
108
+ os_version?: string;
109
+ /**
110
+ * The user agent string.
111
+ */
112
+ user_agent?: string;
85
113
  /**
86
114
  * The SDK version.
87
115
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@carter-rmn/cpix-js",
3
- "version": "1.0.6",
3
+ "version": "1.0.8",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist"
@@ -14,6 +14,11 @@
14
14
  "require": "./dist/cpix.umd.cjs"
15
15
  }
16
16
  },
17
+ "scripts": {
18
+ "dev": "vite",
19
+ "build": "tsc && vite build",
20
+ "preview": "vite preview"
21
+ },
17
22
  "devDependencies": {
18
23
  "picocolors": "^1.0.0",
19
24
  "rollup-plugin-visualizer": "^5.12.0",
@@ -23,10 +28,5 @@
23
28
  },
24
29
  "dependencies": {
25
30
  "vite-plugin-dts": "^3.8.1"
26
- },
27
- "scripts": {
28
- "dev": "vite",
29
- "build": "tsc && vite build",
30
- "preview": "vite preview"
31
31
  }
32
- }
32
+ }
package/LICENCE DELETED
@@ -1,32 +0,0 @@
1
- Proprietary License
2
-
3
- This software is licensed under the terms of this Proprietary License (the "License"). By using this software, you agree to comply with the terms of this License.
4
-
5
- 1. Grant of License
6
- This software is licensed, not sold, to you by Carter Analytics for use only under the terms of this License. Carter Analytics retains ownership of the software itself and reserves all rights not expressly granted to you.
7
-
8
- 2. Permitted Use
9
- You are granted a non-exclusive, non-transferable, limited license to use the software solely for your personal or internal business purposes, provided you have an active subscription to Carter Analytics's paid supporting service.
10
-
11
- 3. Restrictions
12
- You may not:
13
- a. Redistribute, sell, lease, sublicense, or otherwise transfer the software or any portion thereof.
14
- b. Modify, adapt, translate, reverse engineer, decompile, or disassemble the software.
15
- c. Remove or alter any proprietary notices or labels on the software.
16
-
17
- 4. Intellectual Property
18
- All intellectual property rights in and to the software are and shall remain the exclusive property of Carter Analytics.
19
-
20
- 5. Disclaimer of Warranties
21
- The software is provided "as is" without warranty of any kind, either express or implied, including but not limited to the implied warranties of merchantability and fitness for a particular purpose.
22
-
23
- 6. Limitation of Liability
24
- In no event shall Carter Analytics be liable for any damages whatsoever (including, without limitation, damages for loss of business profits, business interruption, loss of business information, or any other pecuniary loss) arising out of the use of or inability to use this software, even if Carter Analytics has been advised of the possibility of such damages.
25
-
26
- 7. Termination
27
- This License is effective until terminated. Your rights under this License will terminate automatically without notice from Carter Analytics if you fail to comply with any term(s) of this License. Upon termination, you shall cease all use of the software and destroy all copies, full or partial, of the software.
28
-
29
- 8. Governing Law
30
- This License shall be governed by and construed in accordance with the laws of [Your Jurisdiction].
31
-
32
- By using this software, you acknowledge that you have read this License, understand it, and agree to be bound by its terms and conditions.