@oxvo/browser 7.4.50 → 7.5.17
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/cjs/entry.js +11 -1233
- package/dist/cjs/entry.js.map +1 -1
- package/dist/cjs/index.js +5 -1233
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/main/entry.d.ts +1 -1
- package/dist/cjs/main/index.d.ts +1 -2
- package/dist/cjs/main/modules/analytics/dormant.d.ts +3 -0
- package/dist/cjs/main/singleton.d.ts +1 -1
- package/dist/lib/entry.js +11 -1233
- package/dist/lib/entry.js.map +1 -1
- package/dist/lib/index.js +5 -1233
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/main/entry.d.ts +1 -1
- package/dist/lib/main/index.d.ts +1 -2
- package/dist/lib/main/modules/analytics/dormant.d.ts +3 -0
- package/dist/lib/main/singleton.d.ts +1 -1
- package/dist/types/main/entry.d.ts +1 -1
- package/dist/types/main/index.d.ts +1 -2
- package/dist/types/main/modules/analytics/dormant.d.ts +3 -0
- package/dist/types/main/singleton.d.ts +1 -1
- package/package.json +1 -1
package/dist/cjs/index.js
CHANGED
|
@@ -4763,7 +4763,7 @@ class Ticker {
|
|
|
4763
4763
|
* this value is injected during build time via rollup
|
|
4764
4764
|
* */
|
|
4765
4765
|
// @ts-ignore
|
|
4766
|
-
const workerBodyFn = "!function(){\"use strict\";class t{constructor(t,s,i,e=10,n=250,h,r){this.onUnauthorised=s,this.onFailure=i,this.MAX_ATTEMPTS_COUNT=e,this.ATTEMPT_TIMEOUT=n,this.onCompress=h,this.pageNo=r,this.attemptsCount=0,this.busy=!1,this.queue=[],this.token=null,this.lastBatchNum=0,this.inflightKeepaliveBytes=0,this.ingestURL=t+\"/v1/events\",this.analyticsIngestURL=t+\"/v1/analytics\",this.isCompressing=void 0!==h}getQueueStatus(){return 0===this.queue.length&&!this.busy}authorise(t){this.token=t,this.busy||this.sendNext()}push(t,s=\"player\"){if(this.busy||!this.token)this.queue.push({batch:t,dataType:s});else if(this.busy=!0,this.isCompressing&&this.onCompress)this.onCompress(t,s);else{const i=++this.lastBatchNum;this.sendBatch(t,!1,i,s)}}sendNext(){const t=this.queue.shift();if(t)if(this.busy=!0,this.isCompressing&&this.onCompress)this.onCompress(t.batch,t.dataType);else{const s=++this.lastBatchNum;this.sendBatch(t.batch,!1,s,t.dataType)}else this.busy=!1}retry(t,s,i,e=\"player\"){if(this.attemptsCount>=this.MAX_ATTEMPTS_COUNT)return void this.onFailure(`Failed to send batch after ${this.attemptsCount} attempts.`);this.attemptsCount++;const n=new Uint8Array(t);setTimeout((()=>this.sendBatch(n,s,i,e)),this.ATTEMPT_TIMEOUT*this.attemptsCount)}sendBatch(t,s,i,e=\"player\"){var n;if(0===t.length)return console.error(\"OxvoSessions: refusing to send 0-byte batch.\",{batchNum:i,dataType:e,isCompressed:s,batch:t}),this.attemptsCount=0,void this.sendNext();const h=null==i?void 0:i.toString().replace(/^([^_]+)_([^_]+).*/,\"$1_$2_$3\");this.busy=!0;const r={Authorization:`Bearer ${this.token}`,DataType:e};if(s&&(r[\"Content-Encoding\"]=\"gzip\"),null===this.token)return void setTimeout((()=>{this.sendBatch(t,s,`${null!=i?i:\"noBatchNum\"}_newToken`,e)}),500);const a=t.length<65536&&this.inflightKeepaliveBytes+t.length<=65536;a&&(this.inflightKeepaliveBytes+=t.length);const o=()=>{a&&(this.inflightKeepaliveBytes-=t.length)},u=`${null!==(n=this.pageNo)&&void 0!==n?n:\"noPageNum\"}_${null!=h?h:\"noBatchNum\"}`,c=\"analytics\"===e?this.analyticsIngestURL:this.ingestURL;fetch(`${c}?seq=${u}&keepalive=${a?\"yes\":\"no\"}`,{body:t,method:\"POST\",headers:r,keepalive:a}).then((n=>{var h;return o(),null===(h=n.body)||void 0===h||h.cancel().catch((()=>{})),401===n.status?(this.busy=!1,void this.onUnauthorised()):413===n.status?(console.warn(\"OxvoSessions: ingest batch was rejected as too large; continuing with the next batch.\"),this.attemptsCount=0,void this.sendNext()):void(n.status>=400?this.retry(t,s,`${null!=i?i:\"noBatchNum\"}_network:${n.status}`,e):(this.attemptsCount=0,this.sendNext()))})).catch((n=>{o(),console.warn(\"OxvoSessions:\",n),this.retry(t,s,`${null!=i?i:\"noBatchNum\"}_reject:${n.message}`,e)}))}sendCompressed(t,s=\"player\"){const i=++this.lastBatchNum;this.sendBatch(t,!0,i,s)}sendUncompressed(t,s=\"player\"){const i=++this.lastBatchNum;this.sendBatch(t,!1,i,s)}clean(){this.sendNext(),setTimeout((()=>{this.token=null,this.queue.length=0}),10)}}const s=new Set([60,61,71,73]),i=new Set([21,22,40,41,44,45,46,47,48,79,83,84,85,87,89,116,120,121,123]),e=new Set([17,23,24,27,28,29,30,42,63,64,78,112,115,124]),n=\"function\"==typeof TextEncoder?new TextEncoder:{encode(t){const s=t.length,i=new Uint8Array(3*s);let e=-1;for(let n=0,h=0,r=0;r!==s;){if(n=t.charCodeAt(r),r+=1,n>=55296&&n<=56319){if(r===s){i[e+=1]=239,i[e+=1]=191,i[e+=1]=189;break}if(h=t.charCodeAt(r),!(h>=56320&&h<=57343)){i[e+=1]=239,i[e+=1]=191,i[e+=1]=189;continue}if(n=1024*(n-55296)+h-56320+65536,r+=1,n>65535){i[e+=1]=240|n>>>18,i[e+=1]=128|n>>>12&63,i[e+=1]=128|n>>>6&63,i[e+=1]=128|63&n;continue}}n<=127?i[e+=1]=0|n:n<=2047?(i[e+=1]=192|n>>>6,i[e+=1]=128|63&n):(i[e+=1]=224|n>>>12,i[e+=1]=128|n>>>6&63,i[e+=1]=128|63&n)}return i.subarray(0,e+1)}};class h{constructor(t){this.size=t,this.offset=0,this.checkpointOffset=0,this.data=new Uint8Array(t)}getCurrentOffset(){return this.offset}getCurrentCheckpoint(){return this.checkpointOffset}checkpoint(){this.checkpointOffset=this.offset}get isEmpty(){return 0===this.offset}skip(t){return this.offset+=t,this.offset<=this.size}set(t,s){this.data.set(t,s)}boolean(t){return this.data[this.offset++]=+t,this.offset<=this.size}uint(t){for((t<0||t>Number.MAX_SAFE_INTEGER)&&(t=0);t>=128;)this.data[this.offset++]=t%256|128,t=Math.floor(t/128);return this.data[this.offset++]=t,this.offset<=this.size}int(t){return t=Math.round(t),this.uint(t>=0?2*t:-2*t-1)}string(t){const s=n.encode(t),i=s.byteLength;return!(!this.uint(i)||this.offset+i>this.size)&&(this.data.set(s,this.offset),this.offset+=i,!0)}reset(){this.offset=0,this.checkpointOffset=0}rewind(t,s){t>this.offset||s>this.checkpointOffset||(this.offset=t,this.checkpointOffset=s)}flush(){const t=this.data.slice(0,this.checkpointOffset);return this.reset(),t}}class r extends h{encode(t){switch(t[0]){case 0:case 11:case 114:case 115:return this.uint(t[1]);case 4:case 44:case 47:return this.string(t[1])&&this.string(t[2])&&this.uint(t[3]);case 5:case 20:case 65:case 70:case 75:case 76:case 77:return this.uint(t[1])&&this.uint(t[2]);case 6:return this.int(t[1])&&this.int(t[2]);case 7:return!0;case 8:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.string(t[4])&&this.boolean(t[5]);case 9:case 10:case 24:case 35:case 51:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3]);case 12:case 52:case 61:case 71:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3]);case 13:case 14:case 17:case 34:case 36:case 50:case 54:return this.uint(t[1])&&this.string(t[2]);case 16:return this.uint(t[1])&&this.int(t[2])&&this.int(t[3]);case 18:return this.uint(t[1])&&this.string(t[2])&&this.int(t[3]);case 19:return this.uint(t[1])&&this.boolean(t[2]);case 21:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4])&&this.string(t[5])&&this.uint(t[6])&&this.uint(t[7])&&this.uint(t[8]);case 22:case 27:case 30:case 41:case 45:case 46:case 43:case 63:case 64:case 79:case 124:return this.string(t[1])&&this.string(t[2]);case 23:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.uint(t[4])&&this.uint(t[5])&&this.uint(t[6])&&this.uint(t[7])&&this.uint(t[8])&&this.uint(t[9]);case 28:case 29:case 42:case 117:case 118:return this.string(t[1]);case 40:return this.string(t[1])&&this.uint(t[2])&&this.string(t[3])&&this.string(t[4]);case 48:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4])&&this.int(t[5]);case 49:return this.int(t[1])&&this.int(t[2])&&this.uint(t[3])&&this.uint(t[4]);case 53:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.uint(t[4])&&this.uint(t[5])&&this.uint(t[6])&&this.string(t[7])&&this.string(t[8]);case 55:return this.boolean(t[1]);case 57:case 60:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4]);case 58:case 120:return this.int(t[1]);case 68:return this.uint(t[1])&&this.uint(t[2])&&this.string(t[3])&&this.string(t[4])&&this.uint(t[5])&&this.uint(t[6]);case 69:return this.uint(t[1])&&this.uint(t[2])&&this.string(t[3])&&this.string(t[4]);case 73:return this.uint(t[1])&&this.string(t[2])&&this.uint(t[3])&&this.string(t[4]);case 78:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4]);case 81:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.int(t[4])&&this.string(t[5]);case 83:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4])&&this.string(t[5])&&this.uint(t[6])&&this.uint(t[7])&&this.uint(t[8])&&this.uint(t[9]);case 84:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.uint(t[4])&&this.string(t[5])&&this.string(t[6]);case 85:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.uint(t[4])&&this.uint(t[5])&&this.uint(t[6])&&this.string(t[7])&&this.string(t[8])&&this.uint(t[9])&&this.boolean(t[10])&&this.uint(t[11])&&this.uint(t[12])&&this.uint(t[13])&&this.uint(t[14])&&this.uint(t[15])&&this.uint(t[16])&&this.uint(t[17]);case 87:return this.string(t[1])&&this.int(t[2])&&this.int(t[3]);case 89:return this.string(t[1])&&this.int(t[2])&&this.int(t[3])&&this.int(t[4])&&this.int(t[5])&&this.string(t[6]);case 112:return this.uint(t[1])&&this.string(t[2])&&this.boolean(t[3])&&this.string(t[4])&&this.int(t[5])&&this.int(t[6]);case 113:return this.uint(t[1])&&this.uint(t[2])&&this.string(t[3]);case 116:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.uint(t[4])&&this.uint(t[5])&&this.uint(t[6])&&this.string(t[7])&&this.string(t[8])&&this.uint(t[9])&&this.boolean(t[10]);case 119:return this.string(t[1])&&this.uint(t[2]);case 121:return this.string(t[1])&&this.string(t[2])&&this.uint(t[3])&&this.uint(t[4]);case 122:return this.string(t[1])&&this.string(t[2])&&this.uint(t[3])&&this.string(t[4]);case 123:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4])&&this.uint(t[5])}}}class a{constructor(t,s,i,e=Number.POSITIVE_INFINITY){this.bufferSize=t,this.version=s,this.dataType=i,this.messageCountLimit=e,this.sizeBuffer=new Uint8Array(3),this.snap=null,this.hasNonTimestamp=!1,this.lastPushedTs=0,this.messageCount=0,this.encoder=new r(t)}push(t,s){const i=this.encoder,e=null===this.snap,n=i.getCurrentOffset(),h=i.getCurrentCheckpoint(),r=this.messageCount;if(e){const t={pageNo:s.pageNo,firstIndex:s.index,timestamp:s.timestamp,url:s.url,tabId:s.tabId};if(!this.writeHeader(t))return i.rewind(n,h),this.messageCount=r,!1;this.snap=t,this.lastPushedTs=s.timestamp}return 0===t[0]||s.timestamp===this.lastPushedTs||this.writeMessageWithSize([0,s.timestamp])?this.writeMessageWithSize(t)?(this.lastPushedTs=s.timestamp,0!==t[0]&&(this.hasNonTimestamp=!0),!0):(i.rewind(n,h),this.messageCount=r,e&&(this.snap=null),!1):(i.rewind(n,h),this.messageCount=r,!1)}hasContent(){return null!==this.snap&&this.hasNonTimestamp}flush(){if(!this.hasContent())return this.reset(),null;const t=this.encoder.flush();return this.snap=null,this.hasNonTimestamp=!1,this.lastPushedTs=0,this.messageCount=0,t}reset(){this.encoder.reset(),this.snap=null,this.hasNonTimestamp=!1,this.lastPushedTs=0,this.messageCount=0}writeHeader(t){const s=this.encoder,i=[81,this.version,t.pageNo,t.firstIndex,t.timestamp,t.url];return!!this.canWriteMessage()&&(!!s.uint(i[0])&&(!!s.encode(i)&&(!(s.getCurrentOffset()>this.bufferSize)&&(s.checkpoint(),this.messageCount++,!!this.writeMessageWithSize([0,t.timestamp])&&!!this.writeMessageWithSize([118,t.tabId])))))}writeMessageWithSize(t){const s=this.encoder;if(!this.canWriteMessage())return!1;if(!s.uint(t[0])||!s.skip(3))return!1;const i=s.getCurrentOffset();if(!s.encode(t))return!1;const e=s.getCurrentOffset(),n=e-i;return n>16777215?(console.warn(\"OxvoSessions: max message size overflow.\"),!1):!(e>this.bufferSize)&&(this.writeSizeAt(n,i-3),s.checkpoint(),this.messageCount++,!0)}canWriteMessage(){return this.messageCount<this.messageCountLimit}writeSizeAt(t,s){for(let s=0;s<3;s++)this.sizeBuffer[s]=t>>8*s;this.encoder.set(this.sizeBuffer,s)}}class o{constructor(t,s,i,e,n,h,r=!1,a){this.pageNo=t,this.timestamp=s,this.url=i,this.onBatch=e,this.tabId=n,this.onOfflineEnd=h,this.localDebug=r,this.onLocalSave=a,this.nextIndex=0,this.beaconSize=2e5,this.beaconSizeLimit=1e6,this.protocolVersion=1,this.playerBuilder=this.createBuilder(this.beaconSize,this.playerVersion(),\"player\"),this.assetBuilder=this.createBuilder(this.beaconSize,3,\"assets\"),this.devtoolsBuilder=this.createBuilder(this.beaconSize,4,\"devtools\"),this.analyticsBuilder=this.createBuilder(this.beaconSize,5,\"analytics\")}playerVersion(){return 2===this.protocolVersion?2:1}currentCtx(){return{pageNo:this.pageNo,index:this.nextIndex,timestamp:this.timestamp,url:this.url,tabId:this.tabId}}setBeaconSizeLimit(t){this.beaconSizeLimit=t}setProtocolVersion(t){this.protocolVersion!==t&&(this.protocolVersion=t,this.playerBuilder.reset(),this.playerBuilder=this.createBuilder(this.beaconSize,this.playerVersion(),\"player\"))}writeMessage(t){if(-1===t[0])return this.finaliseBatch(),this.onOfflineEnd();0===t[0]&&(this.timestamp=t[1]),122===t[0]&&(this.url=t[1]);const s=this.routeMessage(t);this.pushTo(s,t)}routeMessage(t){if(2===this.protocolVersion){const n=t[0];if(s.has(n))return this.assetBuilder;if(i.has(n))return this.devtoolsBuilder;if(e.has(n))return this.analyticsBuilder}return this.playerBuilder}pushTo(t,s){const i=this.currentCtx();if(t.push(s,i))return void this.nextIndex++;if(this.flushBuilder(t),t.push(s,i))return void this.nextIndex++;const e=this.createBuilder(this.beaconSizeLimit,t.version,t.dataType);if(!e.push(s,i))return void console.warn(\"OxvoSessions: beacon size overflow. Skipping large message.\",s);this.nextIndex++;const n=e.flush();n&&this.emitBatch(n,t.dataType,!1)}flushBuilder(t,s=!1){const i=t.flush();return!!i&&(this.emitBatch(i,t.dataType,s),!0)}emitBatch(t,s,i){this.localDebug&&this.onLocalSave&&this.onLocalSave(`${s}-${Date.now()}`,t.slice()),this.onBatch(t,i,s)}createBuilder(t,s,i){return new a(t,s,i,4e3)}finaliseBatch(t=!1){this.flushBuilder(this.playerBuilder,t),this.flushBuilder(this.assetBuilder,t),this.flushBuilder(this.devtoolsBuilder,t),this.flushBuilder(this.analyticsBuilder,t)}clean(){this.playerBuilder.reset(),this.assetBuilder.reset(),this.devtoolsBuilder.reset(),this.analyticsBuilder.reset()}}var u;!function(t){t[t.NotActive=0]=\"NotActive\",t[t.Starting=1]=\"Starting\",t[t.Stopping=2]=\"Stopping\",t[t.Active=3]=\"Active\",t[t.Stopped=4]=\"Stopped\"}(u||(u={}));let c=null,l=null,d=u.NotActive;function p(t){l&&l.finaliseBatch(t)}function g(){return new Promise((t=>{d=u.Stopping,null!==y&&(clearInterval(y),y=null),l&&(l.clean(),l=null),c&&(c.clean(),setTimeout((()=>{c=null}),20)),setTimeout((()=>{d=u.NotActive,t(null)}),100)}))}function f(){[u.Stopped,u.Stopping].includes(d)||(postMessage(\"a_stop\"),g().then((()=>{postMessage(\"a_start\")})))}let m,y=null;self.onmessage=({data:s})=>{var i;if(\"stop\"===s)return p(),void g().then((()=>{d=u.Stopped}));if(\"forceFlushBatch\"!==s)if(\"closing\"!==s){if(!Array.isArray(s)){if(\"compressed\"===s.type){if(!c)return console.debug(\"OR WebWorker: sender not initialised. Compressed batch.\"),void f();s.batch&&c.sendCompressed(s.batch,s.dataType)}if(\"uncompressed\"===s.type){if(!c)return console.debug(\"OR WebWorker: sender not initialised. Uncompressed batch.\"),void f();s.batch&&c.sendUncompressed(s.batch,s.dataType)}return\"start\"===s.type?(d=u.Starting,c=new t(s.ingestPoint,(()=>{f()}),(t=>{!function(t){postMessage({type:\"failure\",reason:t}),g()}(t)}),s.connAttemptCount,s.connAttemptGap,((t,s)=>{postMessage({type:\"compress\",batch:t,dataType:s},[t.buffer])}),s.pageNo),l=new o(s.pageNo,s.timestamp,s.url,((t,s,i=\"player\")=>{c&&(s?c.sendUncompressed(t,i):c.push(t,i))}),s.tabId,(()=>postMessage({type:\"queue_empty\"})),null!==(i=s.localDebug)&&void 0!==i&&i,((t,s)=>{postMessage({type:\"local_save\",name:t,batch:s},[s.buffer])})),null===y&&(y=setInterval(p,3e4)),d=u.Active):\"auth\"===s.type?c?l?(c.authorise(s.token),s.beaconSizeLimit&&l.setBeaconSizeLimit(s.beaconSizeLimit),void(s.protocolVersion&&l.setProtocolVersion(s.protocolVersion))):(console.debug(\"OR WebWorker: writer not initialised. Received auth.\"),void f()):(console.debug(\"OR WebWorker: sender not initialised. Received auth.\"),void f()):void 0}if(l){const t=l;s.forEach((s=>{55===s[0]&&(s[1]?m=setTimeout((()=>f()),18e5):clearTimeout(m)),t.writeMessage(s)}))}else postMessage(\"not_init\"),f()}else p(!0);else p()}}();\n";
|
|
4766
|
+
const workerBodyFn = "!function(){\"use strict\";class t{constructor(t,s,e,i=10,n=250,h,r){this.onUnauthorised=s,this.onFailure=e,this.MAX_ATTEMPTS_COUNT=i,this.ATTEMPT_TIMEOUT=n,this.onCompress=h,this.pageNo=r,this.attemptsCount=0,this.busy=!1,this.queue=[],this.token=null,this.lastBatchNum=0,this.inflightKeepaliveBytes=0,this.ingestURL=t+\"/v1/events\",this.analyticsIngestURL=t+\"/v1/analytics\",this.isCompressing=void 0!==h}getQueueStatus(){return 0===this.queue.length&&!this.busy}authorise(t){this.token=t,this.busy||this.sendNext()}push(t,s=\"player\"){if(this.busy||!this.token)this.queue.push({batch:t,dataType:s});else if(this.busy=!0,this.isCompressing&&this.onCompress)this.onCompress(t,s);else{const e=++this.lastBatchNum;this.sendBatch(t,!1,e,s)}}sendNext(){const t=this.queue.shift();if(t)if(this.busy=!0,this.isCompressing&&this.onCompress)this.onCompress(t.batch,t.dataType);else{const s=++this.lastBatchNum;this.sendBatch(t.batch,!1,s,t.dataType)}else this.busy=!1}retry(t,s,e,i=\"player\"){if(this.attemptsCount>=this.MAX_ATTEMPTS_COUNT)return void this.onFailure(`Failed to send batch after ${this.attemptsCount} attempts.`);this.attemptsCount++;const n=new Uint8Array(t);setTimeout((()=>this.sendBatch(n,s,e,i)),this.ATTEMPT_TIMEOUT*this.attemptsCount)}sendBatch(t,s,e,i=\"player\"){var n;if(0===t.length)return console.error(\"OxvoSessions: refusing to send 0-byte batch.\",{batchNum:e,dataType:i,isCompressed:s,batch:t}),this.attemptsCount=0,void this.sendNext();const h=null==e?void 0:e.toString().replace(/^([^_]+)_([^_]+).*/,\"$1_$2_$3\");this.busy=!0;const r={Authorization:`Bearer ${this.token}`,DataType:i};if(s&&(r[\"Content-Encoding\"]=\"gzip\"),null===this.token)return void setTimeout((()=>{this.sendBatch(t,s,`${null!=e?e:\"noBatchNum\"}_newToken`,i)}),500);const a=t.length<65536&&this.inflightKeepaliveBytes+t.length<=65536;a&&(this.inflightKeepaliveBytes+=t.length);const o=()=>{a&&(this.inflightKeepaliveBytes-=t.length)},u=`${null!==(n=this.pageNo)&&void 0!==n?n:\"noPageNum\"}_${null!=h?h:\"noBatchNum\"}`,c=\"analytics\"===i?this.analyticsIngestURL:this.ingestURL;fetch(`${c}?seq=${u}&keepalive=${a?\"yes\":\"no\"}`,{body:t,method:\"POST\",headers:r,keepalive:a}).then((n=>{var h;return o(),null===(h=n.body)||void 0===h||h.cancel().catch((()=>{})),401===n.status?(this.busy=!1,void this.onUnauthorised()):413===n.status?(console.warn(\"OxvoSessions: ingest batch was rejected as too large; continuing with the next batch.\"),this.attemptsCount=0,void this.sendNext()):void(n.status>=400?this.retry(t,s,`${null!=e?e:\"noBatchNum\"}_network:${n.status}`,i):(this.attemptsCount=0,this.sendNext()))})).catch((n=>{o(),console.warn(\"OxvoSessions:\",n),this.retry(t,s,`${null!=e?e:\"noBatchNum\"}_reject:${n.message}`,i)}))}sendCompressed(t,s=\"player\"){const e=++this.lastBatchNum;this.sendBatch(t,!0,e,s)}sendUncompressed(t,s=\"player\"){const e=++this.lastBatchNum;this.sendBatch(t,!1,e,s)}clean(){this.sendNext(),setTimeout((()=>{this.token=null,this.queue.length=0}),10)}}const s=new Set([60,61,71,73]),e=new Set([21,22,40,41,44,45,46,47,48,79,83,84,85,87,89,116,120,121,123]),i=\"function\"==typeof TextEncoder?new TextEncoder:{encode(t){const s=t.length,e=new Uint8Array(3*s);let i=-1;for(let n=0,h=0,r=0;r!==s;){if(n=t.charCodeAt(r),r+=1,n>=55296&&n<=56319){if(r===s){e[i+=1]=239,e[i+=1]=191,e[i+=1]=189;break}if(h=t.charCodeAt(r),!(h>=56320&&h<=57343)){e[i+=1]=239,e[i+=1]=191,e[i+=1]=189;continue}if(n=1024*(n-55296)+h-56320+65536,r+=1,n>65535){e[i+=1]=240|n>>>18,e[i+=1]=128|n>>>12&63,e[i+=1]=128|n>>>6&63,e[i+=1]=128|63&n;continue}}n<=127?e[i+=1]=0|n:n<=2047?(e[i+=1]=192|n>>>6,e[i+=1]=128|63&n):(e[i+=1]=224|n>>>12,e[i+=1]=128|n>>>6&63,e[i+=1]=128|63&n)}return e.subarray(0,i+1)}};class n{constructor(t){this.size=t,this.offset=0,this.checkpointOffset=0,this.data=new Uint8Array(t)}getCurrentOffset(){return this.offset}getCurrentCheckpoint(){return this.checkpointOffset}checkpoint(){this.checkpointOffset=this.offset}get isEmpty(){return 0===this.offset}skip(t){return this.offset+=t,this.offset<=this.size}set(t,s){this.data.set(t,s)}boolean(t){return this.data[this.offset++]=+t,this.offset<=this.size}uint(t){for((t<0||t>Number.MAX_SAFE_INTEGER)&&(t=0);t>=128;)this.data[this.offset++]=t%256|128,t=Math.floor(t/128);return this.data[this.offset++]=t,this.offset<=this.size}int(t){return t=Math.round(t),this.uint(t>=0?2*t:-2*t-1)}string(t){const s=i.encode(t),e=s.byteLength;return!(!this.uint(e)||this.offset+e>this.size)&&(this.data.set(s,this.offset),this.offset+=e,!0)}reset(){this.offset=0,this.checkpointOffset=0}rewind(t,s){t>this.offset||s>this.checkpointOffset||(this.offset=t,this.checkpointOffset=s)}flush(){const t=this.data.slice(0,this.checkpointOffset);return this.reset(),t}}class h extends n{encode(t){switch(t[0]){case 0:case 11:case 114:case 115:return this.uint(t[1]);case 4:case 44:case 47:return this.string(t[1])&&this.string(t[2])&&this.uint(t[3]);case 5:case 20:case 65:case 70:case 75:case 76:case 77:return this.uint(t[1])&&this.uint(t[2]);case 6:return this.int(t[1])&&this.int(t[2]);case 7:return!0;case 8:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.string(t[4])&&this.boolean(t[5]);case 9:case 10:case 24:case 35:case 51:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3]);case 12:case 52:case 61:case 71:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3]);case 13:case 14:case 17:case 34:case 36:case 50:case 54:return this.uint(t[1])&&this.string(t[2]);case 16:return this.uint(t[1])&&this.int(t[2])&&this.int(t[3]);case 18:return this.uint(t[1])&&this.string(t[2])&&this.int(t[3]);case 19:return this.uint(t[1])&&this.boolean(t[2]);case 21:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4])&&this.string(t[5])&&this.uint(t[6])&&this.uint(t[7])&&this.uint(t[8]);case 22:case 27:case 30:case 41:case 45:case 46:case 43:case 63:case 64:case 79:case 124:return this.string(t[1])&&this.string(t[2]);case 23:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.uint(t[4])&&this.uint(t[5])&&this.uint(t[6])&&this.uint(t[7])&&this.uint(t[8])&&this.uint(t[9]);case 28:case 29:case 42:case 117:case 118:return this.string(t[1]);case 40:return this.string(t[1])&&this.uint(t[2])&&this.string(t[3])&&this.string(t[4]);case 48:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4])&&this.int(t[5]);case 49:return this.int(t[1])&&this.int(t[2])&&this.uint(t[3])&&this.uint(t[4]);case 53:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.uint(t[4])&&this.uint(t[5])&&this.uint(t[6])&&this.string(t[7])&&this.string(t[8]);case 55:return this.boolean(t[1]);case 57:case 60:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4]);case 58:case 120:return this.int(t[1]);case 68:return this.uint(t[1])&&this.uint(t[2])&&this.string(t[3])&&this.string(t[4])&&this.uint(t[5])&&this.uint(t[6]);case 69:return this.uint(t[1])&&this.uint(t[2])&&this.string(t[3])&&this.string(t[4]);case 73:return this.uint(t[1])&&this.string(t[2])&&this.uint(t[3])&&this.string(t[4]);case 78:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4]);case 81:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.int(t[4])&&this.string(t[5]);case 83:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4])&&this.string(t[5])&&this.uint(t[6])&&this.uint(t[7])&&this.uint(t[8])&&this.uint(t[9]);case 84:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.uint(t[4])&&this.string(t[5])&&this.string(t[6]);case 85:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.uint(t[4])&&this.uint(t[5])&&this.uint(t[6])&&this.string(t[7])&&this.string(t[8])&&this.uint(t[9])&&this.boolean(t[10])&&this.uint(t[11])&&this.uint(t[12])&&this.uint(t[13])&&this.uint(t[14])&&this.uint(t[15])&&this.uint(t[16])&&this.uint(t[17]);case 87:return this.string(t[1])&&this.int(t[2])&&this.int(t[3]);case 89:return this.string(t[1])&&this.int(t[2])&&this.int(t[3])&&this.int(t[4])&&this.int(t[5])&&this.string(t[6]);case 112:return this.uint(t[1])&&this.string(t[2])&&this.boolean(t[3])&&this.string(t[4])&&this.int(t[5])&&this.int(t[6]);case 113:return this.uint(t[1])&&this.uint(t[2])&&this.string(t[3]);case 116:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.uint(t[4])&&this.uint(t[5])&&this.uint(t[6])&&this.string(t[7])&&this.string(t[8])&&this.uint(t[9])&&this.boolean(t[10]);case 119:return this.string(t[1])&&this.uint(t[2]);case 121:return this.string(t[1])&&this.string(t[2])&&this.uint(t[3])&&this.uint(t[4]);case 122:return this.string(t[1])&&this.string(t[2])&&this.uint(t[3])&&this.string(t[4]);case 123:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4])&&this.uint(t[5])}}}class r{constructor(t,s,e,i=Number.POSITIVE_INFINITY){this.bufferSize=t,this.version=s,this.dataType=e,this.messageCountLimit=i,this.sizeBuffer=new Uint8Array(3),this.snap=null,this.hasNonTimestamp=!1,this.lastPushedTs=0,this.messageCount=0,this.metadataSize=0,this.encoder=new h(t)}push(t,s){const e=this.encoder,i=null===this.snap,n=e.getCurrentOffset(),h=e.getCurrentCheckpoint(),r=this.messageCount;if(i){const t={pageNo:s.pageNo,firstIndex:s.index,timestamp:s.timestamp,url:s.url,tabId:s.tabId};if(!this.writeHeader(t))return e.rewind(n,h),this.messageCount=r,!1;this.snap=t,this.lastPushedTs=s.timestamp}return 0===t[0]||s.timestamp===this.lastPushedTs||this.writeMessageWithSize([0,s.timestamp])?this.writeMessageWithSize(t)?(this.lastPushedTs=s.timestamp,0!==t[0]&&(this.hasNonTimestamp=!0),!0):(e.rewind(n,h),this.messageCount=r,i&&(this.snap=null),!1):(e.rewind(n,h),this.messageCount=r,!1)}hasContent(){return null!==this.snap&&this.hasNonTimestamp}wireMessageCount(){return this.messageCount}flush(t){if(!this.hasContent())return this.reset(),null;const s=this.snap;let e=this.encoder.flush();if(void 0!==t&&t!==s.firstIndex){const i=new h(this.metadataSize+7);if(!i.uint(81)||!i.encode(this.batchMetadata(s,t)))throw new Error(\"OxvoSessions: batch index exceeds its reserved header space.\");i.checkpoint();const n=i.flush(),r=new Uint8Array(n.length+e.length-this.metadataSize);r.set(n),r.set(e.subarray(this.metadataSize),n.length),e=r}return this.reset(),e}reset(){this.encoder.reset(),this.snap=null,this.hasNonTimestamp=!1,this.lastPushedTs=0,this.messageCount=0,this.metadataSize=0}batchMetadata(t,s){return[81,this.version,t.pageNo,s,t.timestamp,t.url]}writeHeader(t){const s=this.encoder;return!!this.canWriteMessage()&&(!!s.uint(81)&&(!!s.encode(this.batchMetadata(t,t.firstIndex))&&(!(s.getCurrentOffset()+7>this.bufferSize)&&(this.metadataSize=s.getCurrentOffset(),s.checkpoint(),this.messageCount++,!!this.writeMessageWithSize([0,t.timestamp])&&!!this.writeMessageWithSize([118,t.tabId])))))}writeMessageWithSize(t){const s=this.encoder;if(!this.canWriteMessage())return!1;if(!s.uint(t[0])||!s.skip(3))return!1;const e=s.getCurrentOffset();if(!s.encode(t))return!1;const i=s.getCurrentOffset(),n=i-e;return n>16777215?(console.warn(\"OxvoSessions: max message size overflow.\"),!1):!(i+7>this.bufferSize)&&(this.writeSizeAt(n,e-3),s.checkpoint(),this.messageCount++,!0)}canWriteMessage(){return this.messageCount<this.messageCountLimit}writeSizeAt(t,s){for(let s=0;s<3;s++)this.sizeBuffer[s]=t>>8*s;this.encoder.set(this.sizeBuffer,s)}}class a{constructor(t,s,e,i,n,h,r=!1,a){this.pageNo=t,this.timestamp=s,this.url=e,this.onBatch=i,this.tabId=n,this.onOfflineEnd=h,this.localDebug=r,this.onLocalSave=a,this.nextIndex=0,this.beaconSize=2e5,this.beaconSizeLimit=1e6,this.protocolVersion=1,this.playerBuilder=this.createBuilder(this.beaconSize,this.playerVersion(),\"player\"),this.assetBuilder=this.createBuilder(this.beaconSize,3,\"assets\"),this.devtoolsBuilder=this.createBuilder(this.beaconSize,4,\"devtools\")}playerVersion(){return 2===this.protocolVersion?2:1}currentCtx(){return{pageNo:this.pageNo,index:this.nextIndex,timestamp:this.timestamp,url:this.url,tabId:this.tabId}}setBeaconSizeLimit(t){this.beaconSizeLimit=t}setProtocolVersion(t){this.protocolVersion!==t&&(this.protocolVersion=t,this.playerBuilder.reset(),this.playerBuilder=this.createBuilder(this.beaconSize,this.playerVersion(),\"player\"))}writeMessage(t){if(-1===t[0])return this.finaliseBatch(),this.onOfflineEnd();0===t[0]&&(this.timestamp=t[1]),122===t[0]&&(this.url=t[1]);const s=this.routeMessage(t);this.pushTo(s,t)}routeMessage(t){if(2===this.protocolVersion){const i=t[0];if(s.has(i))return this.assetBuilder;if(e.has(i))return this.devtoolsBuilder}return this.playerBuilder}pushTo(t,s){const e=this.currentCtx();if(t.push(s,e))return;if(this.flushBuilder(t),t.push(s,e))return;const i=this.createBuilder(this.beaconSizeLimit,t.version,t.dataType);i.push(s,e)?this.flushBuilder(i):console.warn(\"OxvoSessions: beacon size overflow. Skipping large message.\",s)}flushBuilder(t,s=!1){const e=t.wireMessageCount(),i=t.flush(this.nextIndex);return!!i&&(this.nextIndex+=e,this.emitBatch(i,t.dataType,s),!0)}emitBatch(t,s,e){this.localDebug&&this.onLocalSave&&this.onLocalSave(`${s}-${Date.now()}`,t.slice()),this.onBatch(t,e,s)}createBuilder(t,s,e){return new r(t,s,e,4e3)}finaliseBatch(t=!1){this.flushBuilder(this.playerBuilder,t),this.flushBuilder(this.assetBuilder,t),this.flushBuilder(this.devtoolsBuilder,t)}clean(){this.playerBuilder.reset(),this.assetBuilder.reset(),this.devtoolsBuilder.reset()}}var o;!function(t){t[t.NotActive=0]=\"NotActive\",t[t.Starting=1]=\"Starting\",t[t.Stopping=2]=\"Stopping\",t[t.Active=3]=\"Active\",t[t.Stopped=4]=\"Stopped\"}(o||(o={}));let u=null,c=null,l=o.NotActive;function d(t){c&&c.finaliseBatch(t)}function g(){return new Promise((t=>{l=o.Stopping,null!==m&&(clearInterval(m),m=null),c&&(c.clean(),c=null),u&&(u.clean(),setTimeout((()=>{u=null}),20)),setTimeout((()=>{l=o.NotActive,t(null)}),100)}))}function p(){[o.Stopped,o.Stopping].includes(l)||(postMessage(\"a_stop\"),g().then((()=>{postMessage(\"a_start\")})))}let f,m=null;self.onmessage=({data:s})=>{var e;if(\"stop\"===s)return d(),void g().then((()=>{l=o.Stopped}));if(\"forceFlushBatch\"!==s)if(\"closing\"!==s){if(!Array.isArray(s)){if(\"compressed\"===s.type){if(!u)return console.debug(\"OR WebWorker: sender not initialised. Compressed batch.\"),void p();s.batch&&u.sendCompressed(s.batch,s.dataType)}if(\"uncompressed\"===s.type){if(!u)return console.debug(\"OR WebWorker: sender not initialised. Uncompressed batch.\"),void p();s.batch&&u.sendUncompressed(s.batch,s.dataType)}return\"start\"===s.type?(l=o.Starting,u=new t(s.ingestPoint,(()=>{p()}),(t=>{!function(t){postMessage({type:\"failure\",reason:t}),g()}(t)}),s.connAttemptCount,s.connAttemptGap,((t,s)=>{postMessage({type:\"compress\",batch:t,dataType:s},[t.buffer])}),s.pageNo),c=new a(s.pageNo,s.timestamp,s.url,((t,s,e=\"player\")=>{u&&(s?u.sendUncompressed(t,e):u.push(t,e))}),s.tabId,(()=>postMessage({type:\"queue_empty\"})),null!==(e=s.localDebug)&&void 0!==e&&e,((t,s)=>{postMessage({type:\"local_save\",name:t,batch:s},[s.buffer])})),null===m&&(m=setInterval(d,3e4)),l=o.Active):\"auth\"===s.type?u?c?(u.authorise(s.token),s.beaconSizeLimit&&c.setBeaconSizeLimit(s.beaconSizeLimit),void(s.protocolVersion&&c.setProtocolVersion(s.protocolVersion))):(console.debug(\"OR WebWorker: writer not initialised. Received auth.\"),void p()):(console.debug(\"OR WebWorker: sender not initialised. Received auth.\"),void p()):void 0}if(c){const t=c;s.forEach((s=>{55===s[0]&&(s[1]?f=setTimeout((()=>p()),18e5):clearTimeout(f)),t.writeMessage(s)}))}else postMessage(\"not_init\"),p()}else d(!0);else d()}}();\n";
|
|
4767
4767
|
const CANCELED = 'canceled';
|
|
4768
4768
|
const bufferStorageKey = 'or_buffer_1';
|
|
4769
4769
|
const PROTO_VERSION = '2';
|
|
@@ -4893,7 +4893,7 @@ class App {
|
|
|
4893
4893
|
this.stopCallbacks = [];
|
|
4894
4894
|
this.commitCallbacks = [];
|
|
4895
4895
|
this.activityState = ActivityState.NotActive;
|
|
4896
|
-
this.version = '7.
|
|
4896
|
+
this.version = '7.5.17'; // TODO: version compatability check inside each plugin.
|
|
4897
4897
|
this.socketMode = false;
|
|
4898
4898
|
this.compressionThreshold = 24 * 1000;
|
|
4899
4899
|
this.bc = null;
|
|
@@ -8911,9 +8911,9 @@ function axiosSpy (app, instance, opts, sanitize, stringify) {
|
|
|
8911
8911
|
});
|
|
8912
8912
|
}
|
|
8913
8913
|
function isAxiosError(payload) {
|
|
8914
|
-
return isObject
|
|
8914
|
+
return isObject(payload) && payload.isAxiosError === true;
|
|
8915
8915
|
}
|
|
8916
|
-
function isObject
|
|
8916
|
+
function isObject(thing) {
|
|
8917
8917
|
return thing !== null && typeof thing === 'object';
|
|
8918
8918
|
}
|
|
8919
8919
|
|
|
@@ -10339,1198 +10339,6 @@ function webAnimations(app, options = {}) {
|
|
|
10339
10339
|
});
|
|
10340
10340
|
}
|
|
10341
10341
|
|
|
10342
|
-
/**
|
|
10343
|
-
* Detects client browser, OS, and device information
|
|
10344
|
-
*/
|
|
10345
|
-
function uaParse(sWindow) {
|
|
10346
|
-
const unknown = '-';
|
|
10347
|
-
// Screen detection
|
|
10348
|
-
let width = 0;
|
|
10349
|
-
let height = 0;
|
|
10350
|
-
let screenSize = '';
|
|
10351
|
-
if (sWindow.screen.width) {
|
|
10352
|
-
width = sWindow.screen.width;
|
|
10353
|
-
height = sWindow.screen.height;
|
|
10354
|
-
screenSize = `${width} x ${height}`;
|
|
10355
|
-
}
|
|
10356
|
-
// Browser detection
|
|
10357
|
-
const nVer = sWindow.navigator.appVersion ?? '0';
|
|
10358
|
-
const nAgt = sWindow.navigator.userAgent ?? 'unknown';
|
|
10359
|
-
let browser = sWindow.navigator.appName ?? "unknown";
|
|
10360
|
-
let version = String(parseFloat(nVer));
|
|
10361
|
-
let nameOffset;
|
|
10362
|
-
let verOffset;
|
|
10363
|
-
let ix;
|
|
10364
|
-
// Browser detection logic
|
|
10365
|
-
if ((verOffset = nAgt.indexOf('YaBrowser')) !== -1) {
|
|
10366
|
-
browser = 'Yandex';
|
|
10367
|
-
version = nAgt.substring(verOffset + 10);
|
|
10368
|
-
}
|
|
10369
|
-
else if ((verOffset = nAgt.indexOf('SamsungBrowser')) !== -1) {
|
|
10370
|
-
browser = 'Samsung';
|
|
10371
|
-
version = nAgt.substring(verOffset + 15);
|
|
10372
|
-
}
|
|
10373
|
-
else if ((verOffset = nAgt.indexOf('UCBrowser')) !== -1) {
|
|
10374
|
-
browser = 'UC Browser';
|
|
10375
|
-
version = nAgt.substring(verOffset + 10);
|
|
10376
|
-
}
|
|
10377
|
-
else if ((verOffset = nAgt.indexOf('OPR')) !== -1) {
|
|
10378
|
-
browser = 'Opera';
|
|
10379
|
-
version = nAgt.substring(verOffset + 4);
|
|
10380
|
-
}
|
|
10381
|
-
else if ((verOffset = nAgt.indexOf('Opera')) !== -1) {
|
|
10382
|
-
browser = 'Opera';
|
|
10383
|
-
version = nAgt.substring(verOffset + 6);
|
|
10384
|
-
if ((verOffset = nAgt.indexOf('Version')) !== -1) {
|
|
10385
|
-
version = nAgt.substring(verOffset + 8);
|
|
10386
|
-
}
|
|
10387
|
-
}
|
|
10388
|
-
else if ((verOffset = nAgt.indexOf('Edge')) !== -1) {
|
|
10389
|
-
browser = 'Microsoft Legacy Edge';
|
|
10390
|
-
version = nAgt.substring(verOffset + 5);
|
|
10391
|
-
}
|
|
10392
|
-
else if ((verOffset = nAgt.indexOf('Edg')) !== -1) {
|
|
10393
|
-
browser = 'Microsoft Edge';
|
|
10394
|
-
version = nAgt.substring(verOffset + 4);
|
|
10395
|
-
}
|
|
10396
|
-
else if ((verOffset = nAgt.indexOf('MSIE')) !== -1) {
|
|
10397
|
-
browser = 'Microsoft Internet Explorer';
|
|
10398
|
-
version = nAgt.substring(verOffset + 5);
|
|
10399
|
-
}
|
|
10400
|
-
else if ((verOffset = nAgt.indexOf('Chrome')) !== -1) {
|
|
10401
|
-
browser = 'Chrome';
|
|
10402
|
-
version = nAgt.substring(verOffset + 7);
|
|
10403
|
-
}
|
|
10404
|
-
else if ((verOffset = nAgt.indexOf('Safari')) !== -1) {
|
|
10405
|
-
browser = 'Safari';
|
|
10406
|
-
version = nAgt.substring(verOffset + 7);
|
|
10407
|
-
if ((verOffset = nAgt.indexOf('Version')) !== -1) {
|
|
10408
|
-
version = nAgt.substring(verOffset + 8);
|
|
10409
|
-
}
|
|
10410
|
-
}
|
|
10411
|
-
else if ((verOffset = nAgt.indexOf('Firefox')) !== -1) {
|
|
10412
|
-
browser = 'Firefox';
|
|
10413
|
-
version = nAgt.substring(verOffset + 8);
|
|
10414
|
-
}
|
|
10415
|
-
else if (nAgt.indexOf('Trident/') !== -1) {
|
|
10416
|
-
browser = 'Microsoft Internet Explorer';
|
|
10417
|
-
version = nAgt.substring(nAgt.indexOf('rv:') + 3);
|
|
10418
|
-
}
|
|
10419
|
-
else if ((nameOffset = nAgt.lastIndexOf(' ') + 1) < (verOffset = nAgt.lastIndexOf('/'))) {
|
|
10420
|
-
browser = nAgt.substring(nameOffset, verOffset);
|
|
10421
|
-
version = nAgt.substring(verOffset + 1);
|
|
10422
|
-
if (browser.toLowerCase() === browser.toUpperCase()) {
|
|
10423
|
-
browser = sWindow.navigator.appName;
|
|
10424
|
-
}
|
|
10425
|
-
}
|
|
10426
|
-
// Trim the version string
|
|
10427
|
-
if ((ix = version.indexOf(';')) !== -1) {
|
|
10428
|
-
version = version.substring(0, ix);
|
|
10429
|
-
}
|
|
10430
|
-
if ((ix = version.indexOf(' ')) !== -1) {
|
|
10431
|
-
version = version.substring(0, ix);
|
|
10432
|
-
}
|
|
10433
|
-
if ((ix = version.indexOf(')')) !== -1) {
|
|
10434
|
-
version = version.substring(0, ix);
|
|
10435
|
-
}
|
|
10436
|
-
let majorVersion = parseInt(version, 10);
|
|
10437
|
-
if (isNaN(majorVersion)) {
|
|
10438
|
-
version = String(parseFloat(nVer));
|
|
10439
|
-
majorVersion = parseInt(nVer, 10);
|
|
10440
|
-
}
|
|
10441
|
-
// Mobile detection
|
|
10442
|
-
const mobile = /Mobile|mini|Fennec|Android|iP(ad|od|hone)/.test(nVer);
|
|
10443
|
-
// Cookie detection
|
|
10444
|
-
let cookieEnabled = sWindow.navigator.cookieEnabled || false;
|
|
10445
|
-
if (typeof navigator.cookieEnabled === 'undefined' && !cookieEnabled) {
|
|
10446
|
-
sWindow.document.cookie = 'testcookie';
|
|
10447
|
-
cookieEnabled = sWindow.document.cookie.indexOf('testcookie') !== -1;
|
|
10448
|
-
}
|
|
10449
|
-
// OS detection
|
|
10450
|
-
let os = unknown;
|
|
10451
|
-
const clientStrings = [
|
|
10452
|
-
{ s: 'Windows 10', r: /(Windows 10.0|Windows NT 10.0)/ },
|
|
10453
|
-
{ s: 'Windows 8.1', r: /(Windows 8.1|Windows NT 6.3)/ },
|
|
10454
|
-
{ s: 'Windows 8', r: /(Windows 8|Windows NT 6.2)/ },
|
|
10455
|
-
{ s: 'Windows 7', r: /(Windows 7|Windows NT 6.1)/ },
|
|
10456
|
-
{ s: 'Windows Vista', r: /Windows NT 6.0/ },
|
|
10457
|
-
{ s: 'Windows Server 2003', r: /Windows NT 5.2/ },
|
|
10458
|
-
{ s: 'Windows XP', r: /(Windows NT 5.1|Windows XP)/ },
|
|
10459
|
-
{ s: 'Windows 2000', r: /(Windows NT 5.0|Windows 2000)/ },
|
|
10460
|
-
{ s: 'Windows ME', r: /(Win 9x 4.90|Windows ME)/ },
|
|
10461
|
-
{ s: 'Windows 98', r: /(Windows 98|Win98)/ },
|
|
10462
|
-
{ s: 'Windows 95', r: /(Windows 95|Win95|Windows_95)/ },
|
|
10463
|
-
{ s: 'Windows NT 4.0', r: /(Windows NT 4.0|WinNT4.0|WinNT|Windows NT)/ },
|
|
10464
|
-
{ s: 'Windows CE', r: /Windows CE/ },
|
|
10465
|
-
{ s: 'Windows 3.11', r: /Win16/ },
|
|
10466
|
-
{ s: 'Android', r: /Android/ },
|
|
10467
|
-
{ s: 'Open BSD', r: /OpenBSD/ },
|
|
10468
|
-
{ s: 'Sun OS', r: /SunOS/ },
|
|
10469
|
-
{ s: 'Chrome OS', r: /CrOS/ },
|
|
10470
|
-
{ s: 'Linux', r: /(Linux|X11(?!.*CrOS))/ },
|
|
10471
|
-
{ s: 'iOS', r: /(iPhone|iPad|iPod)/ },
|
|
10472
|
-
{ s: 'Mac OS X', r: /Mac OS X/ },
|
|
10473
|
-
{ s: 'Mac OS', r: /(Mac OS|MacPPC|MacIntel|Mac_PowerPC|Macintosh)/ },
|
|
10474
|
-
{ s: 'QNX', r: /QNX/ },
|
|
10475
|
-
{ s: 'UNIX', r: /UNIX/ },
|
|
10476
|
-
{ s: 'BeOS', r: /BeOS/ },
|
|
10477
|
-
{ s: 'OS/2', r: /OS\/2/ },
|
|
10478
|
-
{
|
|
10479
|
-
s: 'Search Bot',
|
|
10480
|
-
r: /(nuhk|Googlebot|Yammybot|Openbot|Slurp|MSNBot|Ask Jeeves\/Teoma|ia_archiver)/,
|
|
10481
|
-
},
|
|
10482
|
-
];
|
|
10483
|
-
// Find matching OS
|
|
10484
|
-
for (const client of clientStrings) {
|
|
10485
|
-
if (client.r.test(nAgt)) {
|
|
10486
|
-
os = client.s;
|
|
10487
|
-
break;
|
|
10488
|
-
}
|
|
10489
|
-
}
|
|
10490
|
-
// OS Version detection
|
|
10491
|
-
let osVersion = unknown;
|
|
10492
|
-
if (/Windows/.test(os)) {
|
|
10493
|
-
const matches = /Windows (.*)/.exec(os);
|
|
10494
|
-
if (matches && matches[1]) {
|
|
10495
|
-
osVersion = matches[1];
|
|
10496
|
-
// Handle Windows 10/11 detection with newer API if available
|
|
10497
|
-
if (osVersion === '10' && 'userAgentData' in sWindow.navigator) {
|
|
10498
|
-
const nav = navigator;
|
|
10499
|
-
if (nav.userAgentData) {
|
|
10500
|
-
nav.userAgentData
|
|
10501
|
-
.getHighEntropyValues(['platformVersion'])
|
|
10502
|
-
.then((ua) => {
|
|
10503
|
-
const version = parseInt(ua.platformVersion.split('.')[0], 10);
|
|
10504
|
-
osVersion = version < 13 ? '10' : '11';
|
|
10505
|
-
})
|
|
10506
|
-
.catch(() => {
|
|
10507
|
-
// ignore errors and keep osVersion as is
|
|
10508
|
-
});
|
|
10509
|
-
}
|
|
10510
|
-
}
|
|
10511
|
-
}
|
|
10512
|
-
os = 'Windows';
|
|
10513
|
-
}
|
|
10514
|
-
// OS version detection for Mac/Android/iOS
|
|
10515
|
-
switch (os) {
|
|
10516
|
-
case 'Mac OS':
|
|
10517
|
-
case 'Mac OS X':
|
|
10518
|
-
case 'Android': {
|
|
10519
|
-
const matches = /(?:Android|Mac OS|Mac OS X|MacPPC|MacIntel|Mac_PowerPC|Macintosh) ([\.\_\d]+)/.exec(nAgt);
|
|
10520
|
-
osVersion = matches && matches[1] ? matches[1] : unknown;
|
|
10521
|
-
break;
|
|
10522
|
-
}
|
|
10523
|
-
case 'iOS': {
|
|
10524
|
-
const matches = /OS (\d+)_(\d+)_?(\d+)?/.exec(nVer);
|
|
10525
|
-
if (matches && matches[1]) {
|
|
10526
|
-
osVersion = `${matches[1]}.${matches[2]}.${parseInt(matches[3] || '0', 10)}`;
|
|
10527
|
-
}
|
|
10528
|
-
break;
|
|
10529
|
-
}
|
|
10530
|
-
}
|
|
10531
|
-
// Return client data
|
|
10532
|
-
return {
|
|
10533
|
-
screen: screenSize,
|
|
10534
|
-
width,
|
|
10535
|
-
height,
|
|
10536
|
-
browser,
|
|
10537
|
-
browserVersion: version,
|
|
10538
|
-
browserMajorVersion: majorVersion,
|
|
10539
|
-
mobile,
|
|
10540
|
-
os,
|
|
10541
|
-
osVersion,
|
|
10542
|
-
cookies: cookieEnabled,
|
|
10543
|
-
};
|
|
10544
|
-
}
|
|
10545
|
-
function isObject(item) {
|
|
10546
|
-
const isNull = item === null;
|
|
10547
|
-
return Boolean(item && typeof item === 'object' && !Array.isArray(item) && !isNull);
|
|
10548
|
-
}
|
|
10549
|
-
function getUTCOffsetString() {
|
|
10550
|
-
const date = new Date();
|
|
10551
|
-
const offsetMinutes = date.getTimezoneOffset();
|
|
10552
|
-
const hours = Math.abs(Math.floor(offsetMinutes / 60));
|
|
10553
|
-
const minutes = Math.abs(offsetMinutes % 60);
|
|
10554
|
-
const sign = offsetMinutes <= 0 ? '+' : '-';
|
|
10555
|
-
const hoursStr = hours.toString().padStart(2, '0');
|
|
10556
|
-
const minutesStr = minutes.toString().padStart(2, '0');
|
|
10557
|
-
return `UTC${sign}${hoursStr}:${minutesStr}`;
|
|
10558
|
-
}
|
|
10559
|
-
|
|
10560
|
-
const refKey = '$__or__initial_ref__$';
|
|
10561
|
-
const distinctIdKey = '$__or__distinct_device_id__$';
|
|
10562
|
-
const utmParamsKey = '$__or__utm_params__$';
|
|
10563
|
-
const superPropKey = '$__or__super_properties__$';
|
|
10564
|
-
const userIdKey = '$__or__user_id__$';
|
|
10565
|
-
const win = 'window' in globalThis
|
|
10566
|
-
? window
|
|
10567
|
-
: {
|
|
10568
|
-
navigator: { userAgent: '' },
|
|
10569
|
-
screen: {},
|
|
10570
|
-
document: {
|
|
10571
|
-
cookie: '',
|
|
10572
|
-
},
|
|
10573
|
-
location: { search: '' },
|
|
10574
|
-
};
|
|
10575
|
-
const doc = 'document' in globalThis ? document : { referrer: '' };
|
|
10576
|
-
const searchEngineList = [
|
|
10577
|
-
'google',
|
|
10578
|
-
'bing',
|
|
10579
|
-
'yahoo',
|
|
10580
|
-
'baidu',
|
|
10581
|
-
'yandex',
|
|
10582
|
-
'duckduckgo',
|
|
10583
|
-
'ecosia',
|
|
10584
|
-
'ask',
|
|
10585
|
-
'aol',
|
|
10586
|
-
'wolframalpha',
|
|
10587
|
-
'startpage',
|
|
10588
|
-
'swisscows',
|
|
10589
|
-
'qwant',
|
|
10590
|
-
'lycos',
|
|
10591
|
-
'dogpile',
|
|
10592
|
-
'info',
|
|
10593
|
-
'teoma',
|
|
10594
|
-
'webcrawler',
|
|
10595
|
-
'naver',
|
|
10596
|
-
'seznam',
|
|
10597
|
-
'perplexity',
|
|
10598
|
-
];
|
|
10599
|
-
class ConstantProperties {
|
|
10600
|
-
constructor(localStorage, sessionStorage) {
|
|
10601
|
-
this.localStorage = localStorage;
|
|
10602
|
-
this.sessionStorage = sessionStorage;
|
|
10603
|
-
this.user_id = null;
|
|
10604
|
-
this.setUserId = (user_id) => {
|
|
10605
|
-
this.user_id = user_id;
|
|
10606
|
-
this.sessionStorage.setItem(userIdKey, user_id ?? '');
|
|
10607
|
-
};
|
|
10608
|
-
this.resetUserId = (hard) => {
|
|
10609
|
-
this.user_id = null;
|
|
10610
|
-
if (hard) {
|
|
10611
|
-
this.deviceId = this.getDistinctDeviceId(true);
|
|
10612
|
-
}
|
|
10613
|
-
};
|
|
10614
|
-
this.getDistinctDeviceId = (force) => {
|
|
10615
|
-
const potentialStored = this.localStorage.getItem(distinctIdKey);
|
|
10616
|
-
if (potentialStored && !force) {
|
|
10617
|
-
return potentialStored;
|
|
10618
|
-
}
|
|
10619
|
-
else {
|
|
10620
|
-
const distinctId = `${Math.random().toString(36).slice(2)}-${Math.random().toString(36).slice(2)}-${Math.random().toString(36).slice(2)}`;
|
|
10621
|
-
this.localStorage.setItem(distinctIdKey, distinctId);
|
|
10622
|
-
return distinctId;
|
|
10623
|
-
}
|
|
10624
|
-
};
|
|
10625
|
-
this.getReferrer = () => {
|
|
10626
|
-
const potentialStored = this.sessionStorage.getItem(refKey);
|
|
10627
|
-
if (potentialStored) {
|
|
10628
|
-
return potentialStored;
|
|
10629
|
-
}
|
|
10630
|
-
else {
|
|
10631
|
-
const ref = doc.referrer;
|
|
10632
|
-
this.sessionStorage.setItem(refKey, ref);
|
|
10633
|
-
return ref;
|
|
10634
|
-
}
|
|
10635
|
-
};
|
|
10636
|
-
this.parseUTM = () => {
|
|
10637
|
-
const potentialStored = this.sessionStorage.getItem(utmParamsKey);
|
|
10638
|
-
if (potentialStored) {
|
|
10639
|
-
const obj = JSON.parse(potentialStored);
|
|
10640
|
-
this.utmSource = obj.utm_source;
|
|
10641
|
-
this.utmMedium = obj.utm_medium;
|
|
10642
|
-
this.utmCampaign = obj.utm_campaign;
|
|
10643
|
-
}
|
|
10644
|
-
else {
|
|
10645
|
-
const searchParams = new URLSearchParams(win.location.search);
|
|
10646
|
-
this.utmSource = searchParams.get('utm_source') || null;
|
|
10647
|
-
this.utmMedium = searchParams.get('utm_medium') || null;
|
|
10648
|
-
this.utmCampaign = searchParams.get('utm_campaign') || null;
|
|
10649
|
-
const obj = {
|
|
10650
|
-
utm_source: this.utmSource,
|
|
10651
|
-
utm_medium: this.utmMedium,
|
|
10652
|
-
utm_campaign: this.utmCampaign,
|
|
10653
|
-
};
|
|
10654
|
-
this.sessionStorage.setItem(utmParamsKey, JSON.stringify(obj));
|
|
10655
|
-
}
|
|
10656
|
-
};
|
|
10657
|
-
this.getSearchEngine = (ref) => {
|
|
10658
|
-
for (const searchEngine of searchEngineList) {
|
|
10659
|
-
if (ref.includes(searchEngine)) {
|
|
10660
|
-
return searchEngine;
|
|
10661
|
-
}
|
|
10662
|
-
}
|
|
10663
|
-
return null;
|
|
10664
|
-
};
|
|
10665
|
-
this.getSuperProperties = () => {
|
|
10666
|
-
const potentialStored = this.localStorage.getItem(superPropKey);
|
|
10667
|
-
if (potentialStored) {
|
|
10668
|
-
return JSON.parse(potentialStored);
|
|
10669
|
-
}
|
|
10670
|
-
else {
|
|
10671
|
-
return {};
|
|
10672
|
-
}
|
|
10673
|
-
};
|
|
10674
|
-
this.saveSuperProperties = (props) => {
|
|
10675
|
-
this.localStorage.setItem(superPropKey, JSON.stringify(props));
|
|
10676
|
-
};
|
|
10677
|
-
this.clearSuperProperties = () => {
|
|
10678
|
-
this.localStorage.setItem(superPropKey, JSON.stringify({}));
|
|
10679
|
-
};
|
|
10680
|
-
const { width, height, browser, browserVersion, browserMajorVersion, os, osVersion, mobile } = uaParse(win);
|
|
10681
|
-
const storedUserId = this.sessionStorage.getItem(userIdKey);
|
|
10682
|
-
if (storedUserId) {
|
|
10683
|
-
this.user_id = storedUserId;
|
|
10684
|
-
}
|
|
10685
|
-
this.os = os;
|
|
10686
|
-
this.osVersion = osVersion;
|
|
10687
|
-
this.browser = `${browser}`;
|
|
10688
|
-
this.browserVersion = `${browserVersion} (${browserMajorVersion})`;
|
|
10689
|
-
this.platform = mobile ? 'mobile' : 'desktop';
|
|
10690
|
-
this.screenHeight = height;
|
|
10691
|
-
this.screenWidth = width;
|
|
10692
|
-
this.initialReferrer = this.getReferrer();
|
|
10693
|
-
this.deviceId = this.getDistinctDeviceId();
|
|
10694
|
-
this.searchEngine = this.getSearchEngine(this.initialReferrer);
|
|
10695
|
-
this.parseUTM();
|
|
10696
|
-
}
|
|
10697
|
-
get all() {
|
|
10698
|
-
return {
|
|
10699
|
-
os: this.os,
|
|
10700
|
-
os_version: this.osVersion,
|
|
10701
|
-
browser: this.browser,
|
|
10702
|
-
browser_version: this.browserVersion,
|
|
10703
|
-
platform: this.platform,
|
|
10704
|
-
screen_height: this.screenHeight,
|
|
10705
|
-
screen_width: this.screenWidth,
|
|
10706
|
-
initial_referrer: this.initialReferrer,
|
|
10707
|
-
utm_source: this.utmSource,
|
|
10708
|
-
utm_medium: this.utmMedium,
|
|
10709
|
-
utm_campaign: this.utmCampaign,
|
|
10710
|
-
user_id: this.user_id,
|
|
10711
|
-
distinct_id: this.deviceId,
|
|
10712
|
-
sdk_edition: 'web',
|
|
10713
|
-
sdk_version: '7.4.50',
|
|
10714
|
-
timezone: getUTCOffsetString(),
|
|
10715
|
-
search_engine: this.searchEngine,
|
|
10716
|
-
};
|
|
10717
|
-
}
|
|
10718
|
-
get defaultPropertyKeys() {
|
|
10719
|
-
return Object.keys(this.all);
|
|
10720
|
-
}
|
|
10721
|
-
get distinctId() {
|
|
10722
|
-
return this.deviceId;
|
|
10723
|
-
}
|
|
10724
|
-
}
|
|
10725
|
-
|
|
10726
|
-
const mutationTypes = {
|
|
10727
|
-
identity: 'identity',
|
|
10728
|
-
deleteUser: 'delete_user',
|
|
10729
|
-
setProperty: 'set_property',
|
|
10730
|
-
setPropertyOnce: 'set_property_once',
|
|
10731
|
-
appendProperty: 'append_property',
|
|
10732
|
-
appendUniqueProperty: 'append_unique_property',
|
|
10733
|
-
incrementProperty: 'increment_property',
|
|
10734
|
-
};
|
|
10735
|
-
const categories = {
|
|
10736
|
-
people: 'user_actions',
|
|
10737
|
-
events: 'events',
|
|
10738
|
-
};
|
|
10739
|
-
const createEvent = (category, type, timestamp, payload) => {
|
|
10740
|
-
if (category === categories.people) {
|
|
10741
|
-
return {
|
|
10742
|
-
category,
|
|
10743
|
-
data: {
|
|
10744
|
-
type,
|
|
10745
|
-
user_id: payload.user_id,
|
|
10746
|
-
payload: payload.properties,
|
|
10747
|
-
timestamp,
|
|
10748
|
-
},
|
|
10749
|
-
};
|
|
10750
|
-
}
|
|
10751
|
-
else {
|
|
10752
|
-
if (!payload) {
|
|
10753
|
-
throw new Error('Payload is required for event creation');
|
|
10754
|
-
}
|
|
10755
|
-
return {
|
|
10756
|
-
category,
|
|
10757
|
-
data: {
|
|
10758
|
-
name: payload.name,
|
|
10759
|
-
payload: payload.properties,
|
|
10760
|
-
timestamp,
|
|
10761
|
-
},
|
|
10762
|
-
};
|
|
10763
|
-
}
|
|
10764
|
-
};
|
|
10765
|
-
|
|
10766
|
-
const reservedProps = ['properties', 'token', 'timestamp'];
|
|
10767
|
-
class Events {
|
|
10768
|
-
constructor(constantProperties, getTimestamp, batcher) {
|
|
10769
|
-
this.constantProperties = constantProperties;
|
|
10770
|
-
this.getTimestamp = getTimestamp;
|
|
10771
|
-
this.batcher = batcher;
|
|
10772
|
-
this.ownProperties = {};
|
|
10773
|
-
/**
|
|
10774
|
-
* Add event to batch with option to send it immediately,
|
|
10775
|
-
* properties are optional and will not be saved as super prop
|
|
10776
|
-
* */
|
|
10777
|
-
this.sendEvent = (eventName, properties, options) => {
|
|
10778
|
-
// add properties
|
|
10779
|
-
const eventProps = {};
|
|
10780
|
-
if (properties) {
|
|
10781
|
-
if (!isObject(properties)) {
|
|
10782
|
-
throw new Error('Properties must be an object');
|
|
10783
|
-
}
|
|
10784
|
-
Object.entries(properties).forEach(([key, value]) => {
|
|
10785
|
-
if (!this.constantProperties.defaultPropertyKeys.includes(key)) {
|
|
10786
|
-
eventProps[key] = value;
|
|
10787
|
-
}
|
|
10788
|
-
});
|
|
10789
|
-
}
|
|
10790
|
-
const eventPayload = {
|
|
10791
|
-
name: eventName,
|
|
10792
|
-
properties: { ...this.ownProperties, ...eventProps },
|
|
10793
|
-
};
|
|
10794
|
-
const event = createEvent(categories.events, undefined, this.getTimestamp(), eventPayload);
|
|
10795
|
-
if (options?.send_immediately) {
|
|
10796
|
-
void this.batcher.sendImmediately(event);
|
|
10797
|
-
}
|
|
10798
|
-
else {
|
|
10799
|
-
this.batcher.addEvent(event);
|
|
10800
|
-
}
|
|
10801
|
-
};
|
|
10802
|
-
/**
|
|
10803
|
-
* creates super property for all events
|
|
10804
|
-
* */
|
|
10805
|
-
this.setProperty = (nameOrProperties, value) => {
|
|
10806
|
-
let changed = false;
|
|
10807
|
-
if (isObject(nameOrProperties)) {
|
|
10808
|
-
Object.entries(nameOrProperties).forEach(([key, val]) => {
|
|
10809
|
-
if (!this.constantProperties.defaultPropertyKeys.includes(key)) {
|
|
10810
|
-
this.ownProperties[key] = val;
|
|
10811
|
-
changed = true;
|
|
10812
|
-
}
|
|
10813
|
-
});
|
|
10814
|
-
}
|
|
10815
|
-
if (typeof nameOrProperties === 'string' && value !== undefined) {
|
|
10816
|
-
if (!this.constantProperties.defaultPropertyKeys.includes(nameOrProperties)) {
|
|
10817
|
-
this.ownProperties[nameOrProperties] = value;
|
|
10818
|
-
changed = true;
|
|
10819
|
-
}
|
|
10820
|
-
}
|
|
10821
|
-
if (changed) {
|
|
10822
|
-
this.constantProperties.saveSuperProperties(this.ownProperties);
|
|
10823
|
-
}
|
|
10824
|
-
};
|
|
10825
|
-
/**
|
|
10826
|
-
* set super property only if it doesn't exist yet
|
|
10827
|
-
* */
|
|
10828
|
-
this.setPropertiesOnce = (nameOrProperties, value) => {
|
|
10829
|
-
let changed = false;
|
|
10830
|
-
if (isObject(nameOrProperties)) {
|
|
10831
|
-
Object.entries(nameOrProperties).forEach(([key, val]) => {
|
|
10832
|
-
if (!this.ownProperties[key] && !reservedProps.includes(key)) {
|
|
10833
|
-
this.ownProperties[key] = val;
|
|
10834
|
-
changed = true;
|
|
10835
|
-
}
|
|
10836
|
-
});
|
|
10837
|
-
}
|
|
10838
|
-
if (typeof nameOrProperties === 'string' && value !== undefined) {
|
|
10839
|
-
if (!this.ownProperties[nameOrProperties] && !reservedProps.includes(nameOrProperties)) {
|
|
10840
|
-
this.ownProperties[nameOrProperties] = value;
|
|
10841
|
-
changed = true;
|
|
10842
|
-
}
|
|
10843
|
-
}
|
|
10844
|
-
if (changed) {
|
|
10845
|
-
this.constantProperties.saveSuperProperties(this.ownProperties);
|
|
10846
|
-
}
|
|
10847
|
-
};
|
|
10848
|
-
/**
|
|
10849
|
-
* removes properties from list of super properties
|
|
10850
|
-
* */
|
|
10851
|
-
this.unsetProperties = (properties) => {
|
|
10852
|
-
let changed = false;
|
|
10853
|
-
if (Array.isArray(properties)) {
|
|
10854
|
-
properties.forEach((key) => {
|
|
10855
|
-
if (this.ownProperties[key] && !reservedProps.includes(key)) {
|
|
10856
|
-
delete this.ownProperties[key];
|
|
10857
|
-
changed = true;
|
|
10858
|
-
}
|
|
10859
|
-
});
|
|
10860
|
-
}
|
|
10861
|
-
else if (this.ownProperties[properties] && !reservedProps.includes(properties)) {
|
|
10862
|
-
delete this.ownProperties[properties];
|
|
10863
|
-
changed = true;
|
|
10864
|
-
}
|
|
10865
|
-
if (changed) {
|
|
10866
|
-
this.constantProperties.saveSuperProperties(this.ownProperties);
|
|
10867
|
-
}
|
|
10868
|
-
};
|
|
10869
|
-
/** clears all super properties */
|
|
10870
|
-
this.reset = () => {
|
|
10871
|
-
this.ownProperties = {};
|
|
10872
|
-
this.constantProperties.clearSuperProperties();
|
|
10873
|
-
};
|
|
10874
|
-
/** mixpanel compatibility */
|
|
10875
|
-
this.register = this.setProperty;
|
|
10876
|
-
this.register_once = this.setPropertiesOnce;
|
|
10877
|
-
this.unregister = this.unsetProperties;
|
|
10878
|
-
this.track = this.sendEvent;
|
|
10879
|
-
this.ownProperties = this.constantProperties.getSuperProperties();
|
|
10880
|
-
}
|
|
10881
|
-
}
|
|
10882
|
-
|
|
10883
|
-
class People {
|
|
10884
|
-
constructor(constantProperties, getTimestamp, onId, batcher) {
|
|
10885
|
-
this.constantProperties = constantProperties;
|
|
10886
|
-
this.getTimestamp = getTimestamp;
|
|
10887
|
-
this.onId = onId;
|
|
10888
|
-
this.batcher = batcher;
|
|
10889
|
-
this.ownProperties = {};
|
|
10890
|
-
this.defaultPropertyKeyMap = {
|
|
10891
|
-
email: 'email',
|
|
10892
|
-
name: 'name',
|
|
10893
|
-
first_name: 'first_name',
|
|
10894
|
-
firstname: 'first_name',
|
|
10895
|
-
last_name: 'last_name',
|
|
10896
|
-
lastname: 'last_name',
|
|
10897
|
-
phone: 'phone',
|
|
10898
|
-
avatar: 'avatar',
|
|
10899
|
-
};
|
|
10900
|
-
this.normalizeUserPropertyKey = (rawKey) => {
|
|
10901
|
-
const trimmed = String(rawKey || '').trim();
|
|
10902
|
-
if (!trimmed)
|
|
10903
|
-
return '';
|
|
10904
|
-
const withoutPrefix = trimmed.startsWith('$') ? trimmed.slice(1) : trimmed;
|
|
10905
|
-
const snake = withoutPrefix
|
|
10906
|
-
.replace(/([a-z0-9])([A-Z])/g, '$1_$2')
|
|
10907
|
-
.replace(/[-\s]+/g, '_');
|
|
10908
|
-
const snakeLower = snake.toLowerCase();
|
|
10909
|
-
if (this.defaultPropertyKeyMap[snakeLower]) {
|
|
10910
|
-
return this.defaultPropertyKeyMap[snakeLower];
|
|
10911
|
-
}
|
|
10912
|
-
return withoutPrefix;
|
|
10913
|
-
};
|
|
10914
|
-
this.normalizeUserProperties = (input) => {
|
|
10915
|
-
if (!input || typeof input !== 'object')
|
|
10916
|
-
return {};
|
|
10917
|
-
const output = {};
|
|
10918
|
-
Object.entries(input).forEach(([key, value]) => {
|
|
10919
|
-
if (value === undefined || value === null)
|
|
10920
|
-
return;
|
|
10921
|
-
const normalizedKey = this.normalizeUserPropertyKey(key);
|
|
10922
|
-
if (!normalizedKey)
|
|
10923
|
-
return;
|
|
10924
|
-
output[normalizedKey] = value;
|
|
10925
|
-
});
|
|
10926
|
-
return output;
|
|
10927
|
-
};
|
|
10928
|
-
this.identify = (user_id, propertiesOrOptions, options) => {
|
|
10929
|
-
if (!user_id || typeof user_id !== 'string') {
|
|
10930
|
-
throw new Error('OR SDK: user_id (string) is required for .identify()');
|
|
10931
|
-
}
|
|
10932
|
-
let properties;
|
|
10933
|
-
let identifyOptions = options;
|
|
10934
|
-
if (propertiesOrOptions && typeof propertiesOrOptions === 'object' && !Array.isArray(propertiesOrOptions)) {
|
|
10935
|
-
const keys = Object.keys(propertiesOrOptions);
|
|
10936
|
-
if (keys.length === 1 && keys[0] === 'fromTracker' && options === undefined) {
|
|
10937
|
-
identifyOptions = propertiesOrOptions;
|
|
10938
|
-
}
|
|
10939
|
-
else {
|
|
10940
|
-
properties = propertiesOrOptions;
|
|
10941
|
-
}
|
|
10942
|
-
}
|
|
10943
|
-
// if user exists already, reset properties
|
|
10944
|
-
if (this.constantProperties.user_id && this.constantProperties.user_id !== user_id) {
|
|
10945
|
-
this.reset();
|
|
10946
|
-
}
|
|
10947
|
-
this.constantProperties.setUserId(user_id);
|
|
10948
|
-
if (!identifyOptions?.fromTracker) {
|
|
10949
|
-
this.onId(user_id);
|
|
10950
|
-
}
|
|
10951
|
-
const identityEvent = createEvent(categories.people, mutationTypes.identity, this.getTimestamp(), { user_id });
|
|
10952
|
-
this.batcher.addEvent(identityEvent);
|
|
10953
|
-
if (properties && Object.keys(properties).length > 0) {
|
|
10954
|
-
const normalized = this.normalizeUserProperties(properties);
|
|
10955
|
-
if (Object.keys(normalized).length > 0) {
|
|
10956
|
-
this.setProperties(normalized);
|
|
10957
|
-
}
|
|
10958
|
-
}
|
|
10959
|
-
};
|
|
10960
|
-
/** Resets user id and own properties
|
|
10961
|
-
*
|
|
10962
|
-
* !hard reset will destroy persistent device id!
|
|
10963
|
-
* */
|
|
10964
|
-
this.reset = (hard) => {
|
|
10965
|
-
this.constantProperties.resetUserId(hard);
|
|
10966
|
-
this.ownProperties = {};
|
|
10967
|
-
};
|
|
10968
|
-
/**
|
|
10969
|
-
* Will delete user and its data from backend, then reset all local properties
|
|
10970
|
-
*/
|
|
10971
|
-
this.deleteUser = () => {
|
|
10972
|
-
const removedUser = this.constantProperties.user_id;
|
|
10973
|
-
if (!removedUser)
|
|
10974
|
-
return;
|
|
10975
|
-
this.constantProperties.setUserId(null);
|
|
10976
|
-
this.ownProperties = {};
|
|
10977
|
-
const deleteEvent = createEvent(categories.people, mutationTypes.deleteUser, undefined, {
|
|
10978
|
-
user_id: removedUser,
|
|
10979
|
-
});
|
|
10980
|
-
this.batcher.addEvent(deleteEvent);
|
|
10981
|
-
this.reset();
|
|
10982
|
-
};
|
|
10983
|
-
/**
|
|
10984
|
-
* set user properties, overwriting existing ones
|
|
10985
|
-
* */
|
|
10986
|
-
this.setProperties = (propertyOrObj, value) => {
|
|
10987
|
-
if (!propertyOrObj) {
|
|
10988
|
-
throw new Error('OR SDK: no user properties provided to set');
|
|
10989
|
-
}
|
|
10990
|
-
const properties = {};
|
|
10991
|
-
if (typeof propertyOrObj === 'string' && propertyOrObj && value) {
|
|
10992
|
-
properties[propertyOrObj] = value;
|
|
10993
|
-
}
|
|
10994
|
-
else if (isObject(propertyOrObj)) {
|
|
10995
|
-
Object.assign(properties, propertyOrObj);
|
|
10996
|
-
}
|
|
10997
|
-
else {
|
|
10998
|
-
throw new Error('OR SDK: invalid user properties provided to set');
|
|
10999
|
-
}
|
|
11000
|
-
Object.entries(properties).forEach(([key, value]) => {
|
|
11001
|
-
if (!this.constantProperties.defaultPropertyKeys.includes(key)) {
|
|
11002
|
-
this.ownProperties[key] = value;
|
|
11003
|
-
}
|
|
11004
|
-
});
|
|
11005
|
-
const setEvent = createEvent(categories.people, mutationTypes.setProperty, undefined, {
|
|
11006
|
-
user_id: this.user_id,
|
|
11007
|
-
properties,
|
|
11008
|
-
});
|
|
11009
|
-
this.batcher.addEvent(setEvent);
|
|
11010
|
-
};
|
|
11011
|
-
/**
|
|
11012
|
-
* Set property if it doesn't exist yet
|
|
11013
|
-
* */
|
|
11014
|
-
this.setPropertiesOnce = (properties) => {
|
|
11015
|
-
if (!isObject(properties)) {
|
|
11016
|
-
throw new Error('Properties must be an object');
|
|
11017
|
-
}
|
|
11018
|
-
Object.entries(properties).forEach(([key, value]) => {
|
|
11019
|
-
if (!this.constantProperties.defaultPropertyKeys.includes(key) && !this.ownProperties[key]) {
|
|
11020
|
-
this.ownProperties[key] = value;
|
|
11021
|
-
}
|
|
11022
|
-
});
|
|
11023
|
-
const setEvent = createEvent(categories.people, mutationTypes.setPropertyOnce, undefined, {
|
|
11024
|
-
user_id: this.user_id,
|
|
11025
|
-
properties,
|
|
11026
|
-
});
|
|
11027
|
-
this.batcher.addEvent(setEvent);
|
|
11028
|
-
};
|
|
11029
|
-
/**
|
|
11030
|
-
* Add value to property (will turn string prop into array)
|
|
11031
|
-
* */
|
|
11032
|
-
this.appendValues = (key, value) => {
|
|
11033
|
-
if (!this.constantProperties.defaultPropertyKeys.includes(key) && this.ownProperties[key]) {
|
|
11034
|
-
if (Array.isArray(this.ownProperties[key])) {
|
|
11035
|
-
this.ownProperties[key].push(value);
|
|
11036
|
-
}
|
|
11037
|
-
else {
|
|
11038
|
-
this.ownProperties[key] = [this.ownProperties[key], value];
|
|
11039
|
-
}
|
|
11040
|
-
}
|
|
11041
|
-
const appendEvent = createEvent(categories.people, mutationTypes.appendProperty, undefined, {
|
|
11042
|
-
properties: { [key]: value },
|
|
11043
|
-
user_id: this.user_id,
|
|
11044
|
-
});
|
|
11045
|
-
this.batcher.addEvent(appendEvent);
|
|
11046
|
-
};
|
|
11047
|
-
/**
|
|
11048
|
-
* Add unique values to property (will turn string prop into array)
|
|
11049
|
-
* */
|
|
11050
|
-
this.appendUniqueValues = (key, value) => {
|
|
11051
|
-
if (!this.ownProperties[key])
|
|
11052
|
-
return;
|
|
11053
|
-
if (Array.isArray(this.ownProperties[key])) {
|
|
11054
|
-
if (!this.ownProperties[key].includes(value)) {
|
|
11055
|
-
this.appendValues(key, value);
|
|
11056
|
-
}
|
|
11057
|
-
}
|
|
11058
|
-
else if (this.ownProperties[key] !== value) {
|
|
11059
|
-
this.appendValues(key, value);
|
|
11060
|
-
}
|
|
11061
|
-
const unionEvent = createEvent(categories.people, mutationTypes.appendUniqueProperty, undefined, {
|
|
11062
|
-
properties: { [key]: value },
|
|
11063
|
-
user_id: this.user_id,
|
|
11064
|
-
});
|
|
11065
|
-
this.batcher.addEvent(unionEvent);
|
|
11066
|
-
};
|
|
11067
|
-
/**
|
|
11068
|
-
* Adds value (incl. negative) to existing numerical property
|
|
11069
|
-
* */
|
|
11070
|
-
this.increment = (key, value) => {
|
|
11071
|
-
if (!this.ownProperties[key]) {
|
|
11072
|
-
this.ownProperties[key] = 0;
|
|
11073
|
-
}
|
|
11074
|
-
if (this.ownProperties[key] && typeof this.ownProperties[key] !== 'number') {
|
|
11075
|
-
throw new Error('OR SDK: Property must be a number to increment');
|
|
11076
|
-
}
|
|
11077
|
-
// @ts-ignore
|
|
11078
|
-
this.ownProperties[key] += value;
|
|
11079
|
-
const incrementEvent = createEvent(categories.people, mutationTypes.incrementProperty, undefined, {
|
|
11080
|
-
user_id: this.user_id,
|
|
11081
|
-
properties: { [key]: value },
|
|
11082
|
-
});
|
|
11083
|
-
this.batcher.addEvent(incrementEvent);
|
|
11084
|
-
};
|
|
11085
|
-
/** mixpanel compatibility */
|
|
11086
|
-
this.union = this.appendUniqueValues;
|
|
11087
|
-
this.set = this.setProperties;
|
|
11088
|
-
this.set_once = this.setPropertiesOnce;
|
|
11089
|
-
this.append = this.appendValues;
|
|
11090
|
-
this.incrementBy = this.increment;
|
|
11091
|
-
}
|
|
11092
|
-
get user_id() {
|
|
11093
|
-
return this.constantProperties.user_id;
|
|
11094
|
-
}
|
|
11095
|
-
}
|
|
11096
|
-
|
|
11097
|
-
/**
|
|
11098
|
-
* Creates batches of events, then sends them at intervals.
|
|
11099
|
-
*/
|
|
11100
|
-
class Batcher {
|
|
11101
|
-
constructor(backendUrl, getToken, init, standalone) {
|
|
11102
|
-
this.backendUrl = backendUrl;
|
|
11103
|
-
this.getToken = getToken;
|
|
11104
|
-
this.init = init;
|
|
11105
|
-
this.standalone = standalone;
|
|
11106
|
-
this.autosendInterval = 5 * 1000;
|
|
11107
|
-
this.retryTimeout = 3 * 1000;
|
|
11108
|
-
this.retryLimit = 3;
|
|
11109
|
-
this.apiEdp = '/v1/insights/stream';
|
|
11110
|
-
this.batch = {
|
|
11111
|
-
[categories.people]: [],
|
|
11112
|
-
[categories.events]: [],
|
|
11113
|
-
};
|
|
11114
|
-
this.intervalId = null;
|
|
11115
|
-
this.stopped = false;
|
|
11116
|
-
this.paused = false;
|
|
11117
|
-
this.onVisibilityChange = () => {
|
|
11118
|
-
this.paused = document.hidden;
|
|
11119
|
-
};
|
|
11120
|
-
}
|
|
11121
|
-
getBatches() {
|
|
11122
|
-
this.batch[categories.people] = this.dedupePeopleEvents();
|
|
11123
|
-
const finalData = {
|
|
11124
|
-
data: {
|
|
11125
|
-
[categories.people]: [...this.batch[categories.people]],
|
|
11126
|
-
[categories.events]: [...this.batch[categories.events]],
|
|
11127
|
-
},
|
|
11128
|
-
};
|
|
11129
|
-
return finalData;
|
|
11130
|
-
}
|
|
11131
|
-
addEvent(event) {
|
|
11132
|
-
this.batch[event.category].push(event.data);
|
|
11133
|
-
}
|
|
11134
|
-
sendImmediately(event) {
|
|
11135
|
-
this.sendBatch({ [event.category]: [event.data] });
|
|
11136
|
-
}
|
|
11137
|
-
/**
|
|
11138
|
-
*
|
|
11139
|
-
* Essentially we're dividing the batch by identify events and squash all same category events into one in each part,
|
|
11140
|
-
* taking priority to the last one
|
|
11141
|
-
*/
|
|
11142
|
-
dedupePeopleEvents() {
|
|
11143
|
-
const peopleEvents = this.batch[categories.people];
|
|
11144
|
-
const finalEvents = [];
|
|
11145
|
-
const currentPart = [];
|
|
11146
|
-
for (let event of peopleEvents) {
|
|
11147
|
-
if (event.type === 'identity') {
|
|
11148
|
-
if (currentPart.length > 0) {
|
|
11149
|
-
finalEvents.push(...this.squashPeopleEvents(currentPart), event);
|
|
11150
|
-
currentPart.length = 0;
|
|
11151
|
-
}
|
|
11152
|
-
else {
|
|
11153
|
-
finalEvents.push(event);
|
|
11154
|
-
}
|
|
11155
|
-
}
|
|
11156
|
-
else {
|
|
11157
|
-
currentPart.push(event);
|
|
11158
|
-
}
|
|
11159
|
-
}
|
|
11160
|
-
if (currentPart.length > 0) {
|
|
11161
|
-
finalEvents.push(...this.squashPeopleEvents(currentPart));
|
|
11162
|
-
}
|
|
11163
|
-
return finalEvents;
|
|
11164
|
-
}
|
|
11165
|
-
squashPeopleEvents(events) {
|
|
11166
|
-
if (!events || events.length === 0) {
|
|
11167
|
-
return [];
|
|
11168
|
-
}
|
|
11169
|
-
const uniqueEventsByType = new Map();
|
|
11170
|
-
for (let event of events) {
|
|
11171
|
-
const prev = uniqueEventsByType.get(event.type);
|
|
11172
|
-
if (prev) {
|
|
11173
|
-
if (event.type === 'increment_property') {
|
|
11174
|
-
const previousValues = Object.entries(prev.payload);
|
|
11175
|
-
const currentValues = Object.entries(event.payload);
|
|
11176
|
-
const uniqueKeys = new Set([...previousValues.map(([key]) => key), ...currentValues.map(([key]) => key)]);
|
|
11177
|
-
const mergedPayload = {};
|
|
11178
|
-
uniqueKeys.forEach((key) => {
|
|
11179
|
-
const prevValue = typeof prev.payload[key] === 'number' ? prev.payload[key] : 0;
|
|
11180
|
-
const currValue = typeof event.payload[key] === 'number' ? event.payload[key] : 0;
|
|
11181
|
-
mergedPayload[key] = prevValue + currValue;
|
|
11182
|
-
});
|
|
11183
|
-
uniqueEventsByType.set(event.type, {
|
|
11184
|
-
type: event.type,
|
|
11185
|
-
timestamp: event.timestamp,
|
|
11186
|
-
payload: mergedPayload,
|
|
11187
|
-
});
|
|
11188
|
-
continue;
|
|
11189
|
-
}
|
|
11190
|
-
// merge payloads, taking priority to the latest one
|
|
11191
|
-
uniqueEventsByType.set(event.type, {
|
|
11192
|
-
type: event.type,
|
|
11193
|
-
timestamp: event.timestamp,
|
|
11194
|
-
payload: { ...(prev.payload ?? {}), ...(event.payload ?? {}) },
|
|
11195
|
-
});
|
|
11196
|
-
}
|
|
11197
|
-
else {
|
|
11198
|
-
uniqueEventsByType.set(event.type, event);
|
|
11199
|
-
}
|
|
11200
|
-
}
|
|
11201
|
-
return Array.from(uniqueEventsByType.values());
|
|
11202
|
-
}
|
|
11203
|
-
sendBatch(batch) {
|
|
11204
|
-
if (this.stopped) {
|
|
11205
|
-
return;
|
|
11206
|
-
}
|
|
11207
|
-
const sentBatch = batch;
|
|
11208
|
-
let attempts = 0;
|
|
11209
|
-
const send = () => {
|
|
11210
|
-
const token = this.getToken();
|
|
11211
|
-
if (!token) {
|
|
11212
|
-
return;
|
|
11213
|
-
}
|
|
11214
|
-
attempts++;
|
|
11215
|
-
return fetch(`${this.backendUrl}${this.apiEdp}`, {
|
|
11216
|
-
method: 'POST',
|
|
11217
|
-
headers: {
|
|
11218
|
-
'Content-Type': 'application/json',
|
|
11219
|
-
Authorization: `Bearer ${token}`,
|
|
11220
|
-
},
|
|
11221
|
-
body: JSON.stringify(sentBatch),
|
|
11222
|
-
})
|
|
11223
|
-
.then(async (response) => {
|
|
11224
|
-
if (response.status === 401) {
|
|
11225
|
-
const body = await response.json().catch(() => null);
|
|
11226
|
-
if (!this.standalone && body?.error === 'token expired') {
|
|
11227
|
-
this.stop();
|
|
11228
|
-
return;
|
|
11229
|
-
}
|
|
11230
|
-
if (attempts < this.retryLimit) {
|
|
11231
|
-
return this.init().then(() => {
|
|
11232
|
-
send();
|
|
11233
|
-
});
|
|
11234
|
-
}
|
|
11235
|
-
return;
|
|
11236
|
-
}
|
|
11237
|
-
if (response.status === 403) {
|
|
11238
|
-
if (attempts < this.retryLimit) {
|
|
11239
|
-
return this.init().then(() => {
|
|
11240
|
-
send();
|
|
11241
|
-
});
|
|
11242
|
-
}
|
|
11243
|
-
return;
|
|
11244
|
-
}
|
|
11245
|
-
if (!response.ok) {
|
|
11246
|
-
throw new Error(`HTTP error! status: ${response.status}`);
|
|
11247
|
-
}
|
|
11248
|
-
})
|
|
11249
|
-
.catch(() => {
|
|
11250
|
-
if (attempts < this.retryLimit) {
|
|
11251
|
-
setTimeout(() => void send(), this.retryTimeout);
|
|
11252
|
-
}
|
|
11253
|
-
});
|
|
11254
|
-
};
|
|
11255
|
-
void send();
|
|
11256
|
-
}
|
|
11257
|
-
startAutosend() {
|
|
11258
|
-
if (this.intervalId) {
|
|
11259
|
-
clearInterval(this.intervalId);
|
|
11260
|
-
}
|
|
11261
|
-
this.paused = document.hidden;
|
|
11262
|
-
document.addEventListener('visibilitychange', this.onVisibilityChange);
|
|
11263
|
-
this.intervalId = setInterval(() => {
|
|
11264
|
-
if (!this.paused) {
|
|
11265
|
-
this.flush();
|
|
11266
|
-
}
|
|
11267
|
-
}, this.autosendInterval);
|
|
11268
|
-
}
|
|
11269
|
-
flush() {
|
|
11270
|
-
const categories = Object.keys(this.batch);
|
|
11271
|
-
const isEmpty = categories.every((category) => this.batch[category].length === 0);
|
|
11272
|
-
if (isEmpty) {
|
|
11273
|
-
return;
|
|
11274
|
-
}
|
|
11275
|
-
this.sendBatch(this.getBatches());
|
|
11276
|
-
categories.forEach((key) => {
|
|
11277
|
-
this.batch[key] = [];
|
|
11278
|
-
});
|
|
11279
|
-
}
|
|
11280
|
-
stop() {
|
|
11281
|
-
this.flush();
|
|
11282
|
-
if (this.intervalId) {
|
|
11283
|
-
clearInterval(this.intervalId);
|
|
11284
|
-
this.intervalId = null;
|
|
11285
|
-
}
|
|
11286
|
-
document.removeEventListener('visibilitychange', this.onVisibilityChange);
|
|
11287
|
-
this.stopped = true;
|
|
11288
|
-
}
|
|
11289
|
-
restart() {
|
|
11290
|
-
this.stopped = false;
|
|
11291
|
-
this.startAutosend();
|
|
11292
|
-
}
|
|
11293
|
-
}
|
|
11294
|
-
|
|
11295
|
-
const STORAGEKEY = '__or_sdk_analytics_token';
|
|
11296
|
-
const START_ATTEMPT_STORAGE_KEY = '__or_sdk_analytics_start_attempt';
|
|
11297
|
-
const START_ATTEMPT_TTL_MS = 24 * 60 * 60 * 1000;
|
|
11298
|
-
const normalizeIngestPoint = (ingest) => {
|
|
11299
|
-
const base = ingest.replace(/\/$/, '');
|
|
11300
|
-
return base.endsWith('/oxvo') ? base : `${base}/oxvo`;
|
|
11301
|
-
};
|
|
11302
|
-
class Analytics {
|
|
11303
|
-
/**
|
|
11304
|
-
* @param localStorage Class or Object that implements Storage-like interface that stores
|
|
11305
|
-
* values persistently like window.localStorage or any other file-based storage
|
|
11306
|
-
*
|
|
11307
|
-
* @param sessionStorage Class or Object that implements Storage-like interface that stores values
|
|
11308
|
-
* on per-session basis like window.sessionStorage or any other in-memory storage
|
|
11309
|
-
*
|
|
11310
|
-
* @param getToken Function that returns token to bind events to a session
|
|
11311
|
-
*
|
|
11312
|
-
* @param getTimestamp returns current timestamp
|
|
11313
|
-
*
|
|
11314
|
-
* @param setUserId callback for people.identify
|
|
11315
|
-
*
|
|
11316
|
-
* @param standalone if true, analytics will manage its own token (instead of using with oxvosessions tracker session)
|
|
11317
|
-
* */
|
|
11318
|
-
constructor(options) {
|
|
11319
|
-
this.token = null;
|
|
11320
|
-
this.standalone = false;
|
|
11321
|
-
this.pendingStartAttempt = null;
|
|
11322
|
-
this._getToken = () => {
|
|
11323
|
-
if (this.standalone) {
|
|
11324
|
-
return this.token;
|
|
11325
|
-
}
|
|
11326
|
-
else {
|
|
11327
|
-
return this.getToken();
|
|
11328
|
-
}
|
|
11329
|
-
};
|
|
11330
|
-
this._getTimestamp = () => {
|
|
11331
|
-
if (this.standalone) {
|
|
11332
|
-
return Date.now();
|
|
11333
|
-
}
|
|
11334
|
-
return this.getTimestamp();
|
|
11335
|
-
};
|
|
11336
|
-
this.init = async () => {
|
|
11337
|
-
if (!this.standalone) {
|
|
11338
|
-
this.batcher.startAutosend();
|
|
11339
|
-
return;
|
|
11340
|
-
}
|
|
11341
|
-
else {
|
|
11342
|
-
const defaultFields = this.constantProperties.all;
|
|
11343
|
-
const apiEdp = `${this.backendUrl}/v1/insights/start`;
|
|
11344
|
-
const data = {
|
|
11345
|
-
projectKey: this.projectKey,
|
|
11346
|
-
os: defaultFields.os,
|
|
11347
|
-
os_version: defaultFields.os_version,
|
|
11348
|
-
browser: defaultFields.browser,
|
|
11349
|
-
browser_version: defaultFields.browser_version,
|
|
11350
|
-
platform: 'web',
|
|
11351
|
-
device_type: defaultFields.platform,
|
|
11352
|
-
screen_height: defaultFields.screen_height,
|
|
11353
|
-
screen_width: defaultFields.screen_width,
|
|
11354
|
-
initial_referrer: defaultFields.initial_referrer,
|
|
11355
|
-
utm_source: defaultFields.utm_source,
|
|
11356
|
-
utm_medium: defaultFields.utm_medium,
|
|
11357
|
-
utm_campaign: defaultFields.utm_campaign,
|
|
11358
|
-
user_id: defaultFields.user_id ?? '',
|
|
11359
|
-
device_id: defaultFields.distinct_id,
|
|
11360
|
-
sdk_edition: defaultFields.sdk_edition,
|
|
11361
|
-
sdk_version: defaultFields.sdk_version,
|
|
11362
|
-
timezone: defaultFields.timezone,
|
|
11363
|
-
search_engine: defaultFields.search_engine,
|
|
11364
|
-
};
|
|
11365
|
-
const attempt = this.startAttempt(JSON.stringify(data));
|
|
11366
|
-
const resp = await fetch(apiEdp, {
|
|
11367
|
-
method: 'POST',
|
|
11368
|
-
headers: {
|
|
11369
|
-
'Content-Type': 'application/json',
|
|
11370
|
-
'Idempotency-Key': attempt.idempotencyKey,
|
|
11371
|
-
},
|
|
11372
|
-
body: attempt.requestBody,
|
|
11373
|
-
});
|
|
11374
|
-
if (!resp.ok) {
|
|
11375
|
-
throw new Error(`HTTP error! status: ${resp.status}`);
|
|
11376
|
-
}
|
|
11377
|
-
const result = await resp.json();
|
|
11378
|
-
if (result.token) {
|
|
11379
|
-
this.token = result.token;
|
|
11380
|
-
this.sessionStorage.setItem(STORAGEKEY, result.token);
|
|
11381
|
-
this.clearStartAttempt();
|
|
11382
|
-
}
|
|
11383
|
-
else {
|
|
11384
|
-
throw new Error('No token received from server');
|
|
11385
|
-
}
|
|
11386
|
-
}
|
|
11387
|
-
};
|
|
11388
|
-
/**
|
|
11389
|
-
* Used by tracker when running in blundled mode
|
|
11390
|
-
*/
|
|
11391
|
-
this.onStart = () => {
|
|
11392
|
-
if (!this.standalone) {
|
|
11393
|
-
this.batcher.restart();
|
|
11394
|
-
}
|
|
11395
|
-
};
|
|
11396
|
-
this.onStop = () => {
|
|
11397
|
-
if (!this.standalone) {
|
|
11398
|
-
this.batcher.stop();
|
|
11399
|
-
}
|
|
11400
|
-
};
|
|
11401
|
-
this.reset = () => {
|
|
11402
|
-
this.people.reset(true);
|
|
11403
|
-
this.events.reset();
|
|
11404
|
-
this.batcher.stop();
|
|
11405
|
-
if (this.standalone) {
|
|
11406
|
-
this.token = null;
|
|
11407
|
-
this.sessionStorage.setItem(STORAGEKEY, '');
|
|
11408
|
-
this.clearStartAttempt();
|
|
11409
|
-
}
|
|
11410
|
-
};
|
|
11411
|
-
/**
|
|
11412
|
-
* COMPATIBILITY LAYER
|
|
11413
|
-
* */
|
|
11414
|
-
/**
|
|
11415
|
-
* Identify a user with an id (e.g. email, username, etc.)
|
|
11416
|
-
* will bind all events and properties (including device_id) to this user
|
|
11417
|
-
*
|
|
11418
|
-
* you will need to manually call people.reset() to clear the id on logout event
|
|
11419
|
-
* */
|
|
11420
|
-
this.identify = (user_id, properties) => {
|
|
11421
|
-
return this.people.identify(user_id, properties);
|
|
11422
|
-
};
|
|
11423
|
-
/**
|
|
11424
|
-
* Add event to batch with option to send it immediately,
|
|
11425
|
-
* properties are optional and will not be saved as super prop
|
|
11426
|
-
* */
|
|
11427
|
-
this.track = (eventName, properties, options) => {
|
|
11428
|
-
return this.events.track(eventName, properties, options);
|
|
11429
|
-
};
|
|
11430
|
-
this.sessionStorage = options.sessionStorage || sessionStorage;
|
|
11431
|
-
this.localStorage = options.localStorage || localStorage;
|
|
11432
|
-
this.backendUrl = normalizeIngestPoint(options.ingestPoint);
|
|
11433
|
-
this.projectKey = options.projectKey;
|
|
11434
|
-
this.getToken = options.getToken || (() => '');
|
|
11435
|
-
this.getTimestamp = options.getTimestamp || (() => Date.now());
|
|
11436
|
-
this.setUserId = options.setUserId || (() => { });
|
|
11437
|
-
this.standalone = !options.notStandalone;
|
|
11438
|
-
this.token = this.sessionStorage.getItem(STORAGEKEY);
|
|
11439
|
-
this.constantProperties = new ConstantProperties(this.localStorage, this.sessionStorage);
|
|
11440
|
-
this.batcher = new Batcher(this.backendUrl, this._getToken, this.init, this.standalone);
|
|
11441
|
-
this.events = new Events(this.constantProperties, this._getTimestamp, this.batcher);
|
|
11442
|
-
this.people = new People(this.constantProperties, this._getTimestamp, this.setUserId, this.batcher);
|
|
11443
|
-
if (options.notStandalone) {
|
|
11444
|
-
this.init();
|
|
11445
|
-
}
|
|
11446
|
-
}
|
|
11447
|
-
loadStartAttempt() {
|
|
11448
|
-
if (this.isValidStartAttempt(this.pendingStartAttempt)) {
|
|
11449
|
-
return this.pendingStartAttempt;
|
|
11450
|
-
}
|
|
11451
|
-
this.pendingStartAttempt = null;
|
|
11452
|
-
let serialized;
|
|
11453
|
-
try {
|
|
11454
|
-
serialized = this.sessionStorage.getItem(START_ATTEMPT_STORAGE_KEY);
|
|
11455
|
-
}
|
|
11456
|
-
catch {
|
|
11457
|
-
return null;
|
|
11458
|
-
}
|
|
11459
|
-
if (!serialized || serialized.length > 1024 * 1024) {
|
|
11460
|
-
return null;
|
|
11461
|
-
}
|
|
11462
|
-
try {
|
|
11463
|
-
const attempt = JSON.parse(serialized);
|
|
11464
|
-
if (this.isValidStartAttempt(attempt)) {
|
|
11465
|
-
this.pendingStartAttempt = attempt;
|
|
11466
|
-
return attempt;
|
|
11467
|
-
}
|
|
11468
|
-
}
|
|
11469
|
-
catch {
|
|
11470
|
-
// Treat corrupt storage as an absent pending attempt.
|
|
11471
|
-
}
|
|
11472
|
-
return null;
|
|
11473
|
-
}
|
|
11474
|
-
isValidStartAttempt(value) {
|
|
11475
|
-
if (typeof value !== 'object' || value === null) {
|
|
11476
|
-
return false;
|
|
11477
|
-
}
|
|
11478
|
-
const attempt = value;
|
|
11479
|
-
const currentTime = Date.now();
|
|
11480
|
-
if (attempt.version !== 1 ||
|
|
11481
|
-
attempt.projectKey !== this.projectKey ||
|
|
11482
|
-
typeof attempt.createdAt !== 'number' ||
|
|
11483
|
-
!Number.isFinite(attempt.createdAt) ||
|
|
11484
|
-
attempt.createdAt > currentTime ||
|
|
11485
|
-
currentTime - attempt.createdAt >= START_ATTEMPT_TTL_MS ||
|
|
11486
|
-
typeof attempt.idempotencyKey !== 'string' ||
|
|
11487
|
-
attempt.idempotencyKey.length < 8 ||
|
|
11488
|
-
attempt.idempotencyKey.length > 128 ||
|
|
11489
|
-
!/^[A-Za-z0-9._:-]+$/.test(attempt.idempotencyKey) ||
|
|
11490
|
-
typeof attempt.requestBody !== 'string' ||
|
|
11491
|
-
attempt.requestBody.length > 1024 * 1024) {
|
|
11492
|
-
return false;
|
|
11493
|
-
}
|
|
11494
|
-
try {
|
|
11495
|
-
const request = JSON.parse(attempt.requestBody);
|
|
11496
|
-
return request.projectKey === this.projectKey;
|
|
11497
|
-
}
|
|
11498
|
-
catch {
|
|
11499
|
-
return false;
|
|
11500
|
-
}
|
|
11501
|
-
}
|
|
11502
|
-
startAttempt(requestBody) {
|
|
11503
|
-
const existing = this.loadStartAttempt();
|
|
11504
|
-
if (existing) {
|
|
11505
|
-
return existing;
|
|
11506
|
-
}
|
|
11507
|
-
const attempt = {
|
|
11508
|
-
version: 1,
|
|
11509
|
-
projectKey: this.projectKey,
|
|
11510
|
-
createdAt: Date.now(),
|
|
11511
|
-
idempotencyKey: `insights:start:${generateRandomId(40)}`,
|
|
11512
|
-
requestBody,
|
|
11513
|
-
};
|
|
11514
|
-
this.pendingStartAttempt = attempt;
|
|
11515
|
-
try {
|
|
11516
|
-
this.sessionStorage.setItem(START_ATTEMPT_STORAGE_KEY, JSON.stringify(attempt));
|
|
11517
|
-
}
|
|
11518
|
-
catch {
|
|
11519
|
-
// The in-memory copy still protects retries within this Analytics instance.
|
|
11520
|
-
}
|
|
11521
|
-
return attempt;
|
|
11522
|
-
}
|
|
11523
|
-
clearStartAttempt() {
|
|
11524
|
-
this.pendingStartAttempt = null;
|
|
11525
|
-
try {
|
|
11526
|
-
this.sessionStorage.setItem(START_ATTEMPT_STORAGE_KEY, '');
|
|
11527
|
-
}
|
|
11528
|
-
catch {
|
|
11529
|
-
// The in-memory copy is still cleared when storage is unavailable.
|
|
11530
|
-
}
|
|
11531
|
-
}
|
|
11532
|
-
}
|
|
11533
|
-
|
|
11534
10342
|
const Messages = _Messages;
|
|
11535
10343
|
const DOCS_SETUP = '/en/sdk';
|
|
11536
10344
|
function processOptions(obj) {
|
|
@@ -11575,7 +10383,7 @@ class API {
|
|
|
11575
10383
|
this.signalStartIssue = (reason, missingApi) => {
|
|
11576
10384
|
const doNotTrack = this.checkDoNotTrack();
|
|
11577
10385
|
console.log("Tracker couldn't start due to:", JSON.stringify({
|
|
11578
|
-
trackerVersion: '7.
|
|
10386
|
+
trackerVersion: '7.5.17',
|
|
11579
10387
|
siteKey: this.options.siteKey,
|
|
11580
10388
|
doNotTrack,
|
|
11581
10389
|
reason: missingApi.length ? `missing api: ${missingApi.join(',')}` : reason,
|
|
@@ -11621,7 +10429,6 @@ class API {
|
|
|
11621
10429
|
this.identify = (id, properties) => {
|
|
11622
10430
|
if (typeof id === 'string' && this.app !== null) {
|
|
11623
10431
|
this.app.session.setUserID(id);
|
|
11624
|
-
this.analytics?.people.identify(id, properties, { fromTracker: true });
|
|
11625
10432
|
}
|
|
11626
10433
|
};
|
|
11627
10434
|
this.handleError = (e, metadata = {}) => {
|
|
@@ -11727,40 +10534,6 @@ class API {
|
|
|
11727
10534
|
}
|
|
11728
10535
|
const app = new App(options.siteKey, options.sessionToken, options, this.signalStartIssue, this.crossdomainMode);
|
|
11729
10536
|
this.app = app;
|
|
11730
|
-
if (options.siteKey && options.analytics?.active) {
|
|
11731
|
-
let isSaas = false;
|
|
11732
|
-
if (!options.endpoint) {
|
|
11733
|
-
isSaas = true;
|
|
11734
|
-
}
|
|
11735
|
-
if (options.endpoint) {
|
|
11736
|
-
const saasHost = 'api.oxvo.com';
|
|
11737
|
-
const urlObj = new URL(options.endpoint);
|
|
11738
|
-
if (urlObj.hostname === saasHost) {
|
|
11739
|
-
isSaas = true;
|
|
11740
|
-
}
|
|
11741
|
-
}
|
|
11742
|
-
const defaultEdp = 'https://api.oxvo.com/oxvo';
|
|
11743
|
-
this.analytics = new Analytics({
|
|
11744
|
-
localStorage: options.localStorage ?? localStorage,
|
|
11745
|
-
sessionStorage: options.sessionStorage ?? sessionStorage,
|
|
11746
|
-
getToken: () => this.getAnalyticsToken(),
|
|
11747
|
-
getTimestamp: () => this.app?.timestamp() ?? Date.now(),
|
|
11748
|
-
setUserId: (id) => {
|
|
11749
|
-
this.app?.session.setUserID(id);
|
|
11750
|
-
},
|
|
11751
|
-
notStandalone: true,
|
|
11752
|
-
ingestPoint: isSaas
|
|
11753
|
-
? defaultEdp
|
|
11754
|
-
: (options.analytics?.endpoint ?? options.endpoint ?? defaultEdp),
|
|
11755
|
-
projectKey: options.siteKey,
|
|
11756
|
-
});
|
|
11757
|
-
app.attachStartCallback(() => {
|
|
11758
|
-
this.analytics?.onStart();
|
|
11759
|
-
});
|
|
11760
|
-
app.attachStopCallback(() => {
|
|
11761
|
-
this.analytics?.onStop();
|
|
11762
|
-
});
|
|
11763
|
-
}
|
|
11764
10537
|
if (!this.crossdomainMode) {
|
|
11765
10538
|
// no need to send iframe viewport data since its a node for us
|
|
11766
10539
|
Viewport(app, options.urls);
|
|
@@ -11854,7 +10627,6 @@ class API {
|
|
|
11854
10627
|
}
|
|
11855
10628
|
if (startOpts?.userID) {
|
|
11856
10629
|
this.app.session.setUserID(startOpts.userID);
|
|
11857
|
-
this.analytics?.people.identify(startOpts.userID, undefined, { fromTracker: true });
|
|
11858
10630
|
}
|
|
11859
10631
|
return this.app.start(startOpts);
|
|
11860
10632
|
}
|