@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.
- package/dist/common/bot-detection.d.ts +23 -0
- package/dist/common/browser.d.ts +7 -0
- package/dist/common/cookie.d.ts +1 -1
- package/dist/cpix.cjs +1 -1
- package/dist/cpix.iife.js +1 -1
- package/dist/cpix.js +307 -127
- package/dist/cpix.umd.cjs +1 -1
- package/dist/modules/carter-analytics.d.ts +1 -0
- package/dist/types/common.types.d.ts +28 -0
- package/package.json +7 -7
- package/LICENCE +0 -32
|
@@ -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
|
+
}
|
package/dist/common/browser.d.ts
CHANGED
|
@@ -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;
|
package/dist/common/cookie.d.ts
CHANGED
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
|
|
2
|
-
var
|
|
3
|
-
var
|
|
4
|
-
const
|
|
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
|
-
],
|
|
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
|
-
},
|
|
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
|
-
},
|
|
21
|
+
}, C = {
|
|
22
22
|
"vite-plugin-dts": "^3.8.1"
|
|
23
|
-
},
|
|
24
|
-
name:
|
|
25
|
-
version:
|
|
26
|
-
type:
|
|
27
|
-
files:
|
|
28
|
-
main:
|
|
29
|
-
module:
|
|
30
|
-
types:
|
|
31
|
-
exports:
|
|
32
|
-
scripts:
|
|
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:
|
|
35
|
-
},
|
|
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:
|
|
42
|
-
package:
|
|
41
|
+
version: f.version,
|
|
42
|
+
package: f.name,
|
|
43
43
|
USER_PROPERTIES: {},
|
|
44
44
|
SESSION_EXPIRY_DAYS: 14,
|
|
45
45
|
COMMON_PROPERTIES: {}
|
|
46
|
-
},
|
|
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
|
-
},
|
|
51
|
+
}, M = [
|
|
52
52
|
"utm_source",
|
|
53
53
|
"utm_medium",
|
|
54
54
|
"utm_term",
|
|
55
55
|
"utm_content",
|
|
56
56
|
"utm_campaign"
|
|
57
|
-
],
|
|
58
|
-
const l = () =>
|
|
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
|
|
71
|
+
class k extends EventTarget {
|
|
72
72
|
constructor(t = {
|
|
73
73
|
maxRetries: 3,
|
|
74
74
|
initialDelay: 1e4,
|
|
75
|
-
consumerHandler: (i) => (
|
|
75
|
+
consumerHandler: (i) => (n.debug("Consuming event:", i), Promise.resolve())
|
|
76
76
|
}) {
|
|
77
77
|
super();
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 (
|
|
104
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 (
|
|
132
|
-
|
|
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
|
|
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 = (
|
|
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(`${
|
|
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
|
|
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(`${
|
|
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:
|
|
191
|
-
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
|
|
249
|
+
throw n.error("Error acquiring access token:", t), new Error("[CPIX] Authentication error");
|
|
198
250
|
}
|
|
199
251
|
}
|
|
200
252
|
}
|
|
201
|
-
class
|
|
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
|
|
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
|
|
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
|
|
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"),
|
|
226
|
-
let
|
|
227
|
-
for (; (
|
|
228
|
-
|
|
229
|
-
return
|
|
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
|
|
289
|
+
class r {
|
|
238
290
|
static prefix() {
|
|
239
|
-
return `__${
|
|
291
|
+
return `__${a.TRACKER_FUNC_NAME}__`;
|
|
240
292
|
}
|
|
241
293
|
static get(e) {
|
|
242
|
-
const 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
|
|
247
|
-
|
|
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 = `${
|
|
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(
|
|
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 !!
|
|
312
|
+
return !!r.get(e);
|
|
261
313
|
}
|
|
262
314
|
static setUtms() {
|
|
263
|
-
const e =
|
|
315
|
+
const e = M;
|
|
264
316
|
let t = !1;
|
|
265
317
|
for (let i = 0; i < e.length; i++) {
|
|
266
|
-
const
|
|
267
|
-
if (
|
|
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
|
|
275
|
-
for (let
|
|
276
|
-
const
|
|
277
|
-
i =
|
|
278
|
-
[
|
|
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
|
-
|
|
282
|
-
|
|
283
|
-
JSON.stringify(
|
|
284
|
-
|
|
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 =
|
|
290
|
-
return
|
|
341
|
+
const e = r.get(o.UTM);
|
|
342
|
+
return g.isPresent(e) ? JSON.parse(e) : {};
|
|
291
343
|
}
|
|
292
|
-
static createSession() {
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
),
|
|
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
|
|
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
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
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
|
|
313
|
-
maxRetries:
|
|
314
|
-
initialDelay:
|
|
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.
|
|
328
|
-
|
|
329
|
-
|
|
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
|
-
|
|
494
|
+
r.exists(o.ACCESS_TOKEN) || (this.accessToken = await d.aquireAccessToken(
|
|
336
495
|
this.instances[0].client_id
|
|
337
|
-
),
|
|
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:
|
|
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:
|
|
520
|
+
user_properties: a.USER_PROPERTIES,
|
|
362
521
|
...this.metaParameters
|
|
363
522
|
});
|
|
364
523
|
};
|
|
365
|
-
history.pushState = (...
|
|
366
|
-
e.apply(history,
|
|
367
|
-
}, history.replaceState = (...
|
|
368
|
-
t.apply(history,
|
|
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 =
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
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:
|
|
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
|
-
|
|
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
|
-
...
|
|
609
|
+
...a.COMMON_PROPERTIES,
|
|
430
610
|
...e.event_properties
|
|
431
|
-
}, e.device && (e.device.cpix_sdk_version =
|
|
432
|
-
const t = await fetch(`${
|
|
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 ${
|
|
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
|
-
),
|
|
444
|
-
|
|
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
|
|
626
|
+
throw n.error("Failed to publish event:", t), new Error("[CPIX] Failed to publish event");
|
|
447
627
|
}
|
|
448
628
|
}
|
|
449
629
|
}
|
|
450
|
-
const
|
|
451
|
-
typeof window < "u" && (window.cpix =
|
|
630
|
+
const O = new N();
|
|
631
|
+
typeof window < "u" && (window.cpix = O);
|
|
452
632
|
export {
|
|
453
|
-
|
|
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"})});
|
|
@@ -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.
|
|
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.
|