@kryptonhq/analytics 0.1.0 → 0.1.1
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/README.md +34 -1
- package/dist/browser.global.js +21 -1
- package/dist/index.d.mts +31 -6
- package/dist/index.d.ts +31 -6
- package/dist/index.js +246 -49
- package/dist/index.mjs +246 -49
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -16,6 +16,8 @@ const krypton = new Krypton({
|
|
|
16
16
|
endpoint: "https://ingest.yourdomain.com",
|
|
17
17
|
autoPageview: true,
|
|
18
18
|
heatmap: true,
|
|
19
|
+
consentRequired: true,
|
|
20
|
+
showConsentBanner: true,
|
|
19
21
|
});
|
|
20
22
|
|
|
21
23
|
krypton.track("signup_clicked", { plan: "pro" });
|
|
@@ -33,7 +35,9 @@ Use jsDelivr:
|
|
|
33
35
|
apiKey: "kapi_xxx",
|
|
34
36
|
endpoint: "https://ingest.yourdomain.com",
|
|
35
37
|
autoPageview: true,
|
|
36
|
-
heatmap: true
|
|
38
|
+
heatmap: true,
|
|
39
|
+
consentRequired: true,
|
|
40
|
+
showConsentBanner: true
|
|
37
41
|
});
|
|
38
42
|
|
|
39
43
|
krypton.track("page_loaded");
|
|
@@ -43,6 +47,35 @@ Use jsDelivr:
|
|
|
43
47
|
|
|
44
48
|
The CDN build exposes a global: `window.KryptonAnalytics`.
|
|
45
49
|
|
|
50
|
+
## Consent (default deny + categories)
|
|
51
|
+
|
|
52
|
+
The SDK supports category-level consent:
|
|
53
|
+
|
|
54
|
+
- `analytics`
|
|
55
|
+
- `heatmaps`
|
|
56
|
+
- `geo` (browser geolocation, if granted by user)
|
|
57
|
+
|
|
58
|
+
Example:
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
import { Krypton } from "@kryptonhq/analytics";
|
|
62
|
+
|
|
63
|
+
const krypton = new Krypton({
|
|
64
|
+
apiKey: "kapi_xxx",
|
|
65
|
+
endpoint: "https://ingest.yourdomain.com",
|
|
66
|
+
heatmap: true,
|
|
67
|
+
consentRequired: true, // default deny
|
|
68
|
+
showConsentBanner: true, // built-in popup
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// Optional manual control
|
|
72
|
+
krypton.setConsent({
|
|
73
|
+
analytics: true,
|
|
74
|
+
heatmaps: false,
|
|
75
|
+
geo: false,
|
|
76
|
+
});
|
|
77
|
+
```
|
|
78
|
+
|
|
46
79
|
### GA-style bootstrap snippet (single paste)
|
|
47
80
|
|
|
48
81
|
```html
|
package/dist/browser.global.js
CHANGED
|
@@ -1 +1,21 @@
|
|
|
1
|
-
"use strict";var KryptonAnalytics=(()=>{var Z=Object.defineProperty;var ke=Object.getOwnPropertyDescriptor;var Se=Object.getOwnPropertyNames;var be=Object.prototype.hasOwnProperty;var Ce=(e,t)=>{for(var r in t)Z(e,r,{get:t[r],enumerable:!0})},Ie=(e,t,r,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of Se(t))!be.call(e,n)&&n!==r&&Z(e,n,{get:()=>t[n],enumerable:!(i=ke(t,n))||i.enumerable});return e};var Te=e=>Ie(Z({},"__esModule",{value:!0}),e);var at={};Ce(at,{Krypton:()=>K,default:()=>nt,init:()=>ye});var g;(function(e){e[e.Document=0]="Document",e[e.DocumentType=1]="DocumentType",e[e.Element=2]="Element",e[e.Text=3]="Text",e[e.CDATA=4]="CDATA",e[e.Comment=5]="Comment"})(g||(g={}));function xe(e){return e.nodeType===e.ELEMENT_NODE}function Ee(e){var t=e?.host;return t?.shadowRoot===e}function ee(e){return Object.prototype.toString.call(e)==="[object ShadowRoot]"}function Le(e){return e.includes(" background-clip: text;")&&!e.includes(" -webkit-background-clip: text;")&&(e=e.replace(" background-clip: text;"," -webkit-background-clip: text; background-clip: text;")),e}function te(e){try{var t=e.rules||e.cssRules;return t?Le(Array.from(t).map(Ne).join("")):null}catch{return null}}function Ne(e){var t=e.cssText;if(_e(e))try{t=te(e.styleSheet)||t}catch{}return t}function _e(e){return"styleSheet"in e}var Re=(function(){function e(){this.idNodeMap=new Map,this.nodeMetaMap=new WeakMap}return e.prototype.getId=function(t){var r;if(!t)return-1;var i=(r=this.getMeta(t))===null||r===void 0?void 0:r.id;return i??-1},e.prototype.getNode=function(t){return this.idNodeMap.get(t)||null},e.prototype.getIds=function(){return Array.from(this.idNodeMap.keys())},e.prototype.getMeta=function(t){return this.nodeMetaMap.get(t)||null},e.prototype.removeNodeFromMap=function(t){var r=this,i=this.getId(t);this.idNodeMap.delete(i),t.childNodes&&t.childNodes.forEach(function(n){return r.removeNodeFromMap(n)})},e.prototype.has=function(t){return this.idNodeMap.has(t)},e.prototype.hasNode=function(t){return this.nodeMetaMap.has(t)},e.prototype.add=function(t,r){var i=r.id;this.idNodeMap.set(i,t),this.nodeMetaMap.set(t,r)},e.prototype.replace=function(t,r){var i=this.getNode(t);if(i){var n=this.nodeMetaMap.get(i);n&&this.nodeMetaMap.set(r,n)}this.idNodeMap.set(t,r)},e.prototype.reset=function(){this.idNodeMap=new Map,this.nodeMetaMap=new WeakMap},e})();function Oe(e){var t=e.maskInputOptions,r=e.tagName,i=e.type,n=e.value,a=e.maskInputFn,c=n||"";return(t[r.toLowerCase()]||t[i])&&(a?c=a(c):c="*".repeat(c.length)),c}var ue="__rrweb_original__";function Me(e){var t=e.getContext("2d");if(!t)return!0;for(var r=50,i=0;i<e.width;i+=r)for(var n=0;n<e.height;n+=r){var a=t.getImageData,c=ue in a?a[ue]:a,l=new Uint32Array(c.call(t,i,n,Math.min(r,e.width-i),Math.min(r,e.height-n)).data.buffer);if(l.some(function(o){return o!==0}))return!1}return!0}var De=1,Ae=new RegExp("[^a-z0-9-_:]"),le=-2;function Fe(){return De++}function Pe(e){if(e instanceof HTMLFormElement)return"form";var t=e.tagName.toLowerCase().trim();return Ae.test(t)?"div":t}function Ue(e){return e.cssRules?Array.from(e.cssRules).map(function(t){return t.cssText||""}).join(""):""}function He(e){var t="";return e.indexOf("//")>-1?t=e.split("/").slice(0,3).join("/"):t=e.split("/")[0],t=t.split("?")[0],t}var z,fe,We=/url\((?:(')([^']*)'|(")(.*?)"|([^)]*))\)/gm,Ge=/^(?!www\.|(?:http|ftp)s?:\/\/|[A-Za-z]:\\|\/\/|#).*/,ze=/^(data:)([^,]*),(.*)/i;function $(e,t){return(e||"").replace(We,function(r,i,n,a,c,l){var o=n||c||l,f=i||a||"";if(!o)return r;if(!Ge.test(o)||ze.test(o))return"url(".concat(f).concat(o).concat(f,")");if(o[0]==="/")return"url(".concat(f).concat(He(t)+o).concat(f,")");var u=t.split("/"),p=o.split("/");u.pop();for(var b=0,w=p;b<w.length;b++){var k=w[b];k!=="."&&(k===".."?u.pop():u.push(k))}return"url(".concat(f).concat(u.join("/")).concat(f,")")})}var je=/^[^ \t\n\r\u000c]+/,Ke=/^[, \t\n\r\u000c]+/;function Be(e,t){if(t.trim()==="")return t;var r=0;function i(f){var u,p=f.exec(t.substring(r));return p?(u=p[0],r+=u.length,u):""}for(var n=[];i(Ke),!(r>=t.length);){var a=i(je);if(a.slice(-1)===",")a=j(e,a.substring(0,a.length-1)),n.push(a);else{var c="";a=j(e,a);for(var l=!1;;){var o=t.charAt(r);if(o===""){n.push((a+c).trim());break}else if(l)o===")"&&(l=!1);else if(o===","){r+=1,n.push((a+c).trim());break}else o==="("&&(l=!0);c+=o,r+=1}}}return n.join(", ")}function j(e,t){if(!t||t.trim()==="")return t;var r=e.createElement("a");return r.href=t,r.href}function Qe(e){return!!(e.tagName==="svg"||e.ownerSVGElement)}function ie(){var e=document.createElement("a");return e.href="",e.href}function $e(e,t,r,i){return r==="src"||r==="href"&&i&&!(t==="use"&&i[0]==="#")||r==="xlink:href"&&i&&i[0]!=="#"||r==="background"&&i&&(t==="table"||t==="td"||t==="th")?j(e,i):r==="srcset"&&i?Be(e,i):r==="style"&&i?$(i,ie()):t==="object"&&r==="data"&&i?j(e,i):i}function qe(e,t,r){if(typeof t=="string"){if(e.classList.contains(t))return!0}else for(var i=e.classList.length;i--;){var n=e.classList[i];if(t.test(n))return!0}return r?e.matches(r):!1}function re(e,t,r){if(!e)return!1;if(e.nodeType!==e.ELEMENT_NODE)return r?re(e.parentNode,t,r):!1;for(var i=e.classList.length;i--;){var n=e.classList[i];if(t.test(n))return!0}return r?re(e.parentNode,t,r):!1}function Je(e,t,r){var i=e.nodeType===e.ELEMENT_NODE?e:e.parentElement;if(i===null)return!1;if(typeof t=="string"){if(i.classList.contains(t)||i.closest(".".concat(t)))return!0}else if(re(i,t,!0))return!0;return!!(r&&(i.matches(r)||i.closest(r)))}function Ye(e,t,r){var i=e.contentWindow;if(i){var n=!1,a;try{a=i.document.readyState}catch{return}if(a!=="complete"){var c=setTimeout(function(){n||(t(),n=!0)},r);e.addEventListener("load",function(){clearTimeout(c),n=!0,t()});return}var l="about:blank";if(i.location.href!==l||e.src===l||e.src==="")return setTimeout(t,0),e.addEventListener("load",t);e.addEventListener("load",t)}}function Ve(e,t,r){var i=!1,n;try{n=e.sheet}catch{return}if(!n){var a=setTimeout(function(){i||(t(),i=!0)},r);e.addEventListener("load",function(){clearTimeout(a),i=!0,t()})}}function Xe(e,t){var r=t.doc,i=t.mirror,n=t.blockClass,a=t.blockSelector,c=t.maskTextClass,l=t.maskTextSelector,o=t.inlineStylesheet,f=t.maskInputOptions,u=f===void 0?{}:f,p=t.maskTextFn,b=t.maskInputFn,w=t.dataURLOptions,k=w===void 0?{}:w,I=t.inlineImages,T=t.recordCanvas,x=t.keepIframeSrcFn,h=t.newlyAddedElement,s=h===void 0?!1:h,y=Ze(r,i);switch(e.nodeType){case e.DOCUMENT_NODE:return e.compatMode!=="CSS1Compat"?{type:g.Document,childNodes:[],compatMode:e.compatMode}:{type:g.Document,childNodes:[]};case e.DOCUMENT_TYPE_NODE:return{type:g.DocumentType,name:e.name,publicId:e.publicId,systemId:e.systemId,rootId:y};case e.ELEMENT_NODE:return tt(e,{doc:r,blockClass:n,blockSelector:a,inlineStylesheet:o,maskInputOptions:u,maskInputFn:b,dataURLOptions:k,inlineImages:I,recordCanvas:T,keepIframeSrcFn:x,newlyAddedElement:s,rootId:y});case e.TEXT_NODE:return et(e,{maskTextClass:c,maskTextSelector:l,maskTextFn:p,rootId:y});case e.CDATA_SECTION_NODE:return{type:g.CDATA,textContent:"",rootId:y};case e.COMMENT_NODE:return{type:g.Comment,textContent:e.textContent||"",rootId:y};default:return!1}}function Ze(e,t){if(t.hasNode(e)){var r=t.getId(e);return r===1?void 0:r}}function et(e,t){var r,i=t.maskTextClass,n=t.maskTextSelector,a=t.maskTextFn,c=t.rootId,l=e.parentNode&&e.parentNode.tagName,o=e.textContent,f=l==="STYLE"?!0:void 0,u=l==="SCRIPT"?!0:void 0;if(f&&o){try{e.nextSibling||e.previousSibling||!((r=e.parentNode.sheet)===null||r===void 0)&&r.cssRules&&(o=Ue(e.parentNode.sheet))}catch(p){console.warn("Cannot get CSS styles from text's parentNode. Error: ".concat(p),e)}o=$(o,ie())}return u&&(o="SCRIPT_PLACEHOLDER"),!f&&!u&&o&&Je(e,i,n)&&(o=a?a(o):o.replace(/[\S]/g,"*")),{type:g.Text,textContent:o||"",isStyle:f,rootId:c}}function tt(e,t){for(var r=t.doc,i=t.blockClass,n=t.blockSelector,a=t.inlineStylesheet,c=t.maskInputOptions,l=c===void 0?{}:c,o=t.maskInputFn,f=t.dataURLOptions,u=f===void 0?{}:f,p=t.inlineImages,b=t.recordCanvas,w=t.keepIframeSrcFn,k=t.newlyAddedElement,I=k===void 0?!1:k,T=t.rootId,x=qe(e,i,n),h=Pe(e),s={},y=e.attributes.length,M=0;M<y;M++){var E=e.attributes[M];s[E.name]=$e(r,h,E.name,E.value)}if(h==="link"&&a){var C=Array.from(r.styleSheets).find(function(N){return N.href===e.href}),m=null;C&&(m=te(C)),m&&(delete s.rel,delete s.href,s._cssText=$(m,C.href))}if(h==="style"&&e.sheet&&!(e.innerText||e.textContent||"").trim().length){var m=te(e.sheet);m&&(s._cssText=$(m,ie()))}if(h==="input"||h==="textarea"||h==="select"){var P=e.value,_=e.checked;s.type!=="radio"&&s.type!=="checkbox"&&s.type!=="submit"&&s.type!=="button"&&P?s.value=Oe({type:s.type,tagName:h,value:P,maskInputOptions:l,maskInputFn:o}):_&&(s.checked=_)}if(h==="option"&&(e.selected&&!l.select?s.selected=!0:delete s.selected),h==="canvas"&&b){if(e.__context==="2d")Me(e)||(s.rr_dataURL=e.toDataURL(u.type,u.quality));else if(!("__context"in e)){var L=e.toDataURL(u.type,u.quality),D=document.createElement("canvas");D.width=e.width,D.height=e.height;var A=D.toDataURL(u.type,u.quality);L!==A&&(s.rr_dataURL=L)}}if(h==="img"&&p){z||(z=r.createElement("canvas"),fe=z.getContext("2d"));var S=e,R=S.crossOrigin;S.crossOrigin="anonymous";var F=function(){try{z.width=S.naturalWidth,z.height=S.naturalHeight,fe.drawImage(S,0,0),s.rr_dataURL=z.toDataURL(u.type,u.quality)}catch(N){console.warn("Cannot inline img src=".concat(S.currentSrc,"! Error: ").concat(N))}R?s.crossOrigin=R:S.removeAttribute("crossorigin")};S.complete&&S.naturalWidth!==0?F():S.onload=F}if((h==="audio"||h==="video")&&(s.rr_mediaState=e.paused?"paused":"played",s.rr_mediaCurrentTime=e.currentTime),I||(e.scrollLeft&&(s.rr_scrollLeft=e.scrollLeft),e.scrollTop&&(s.rr_scrollTop=e.scrollTop)),x){var U=e.getBoundingClientRect(),H=U.width,O=U.height;s={class:s.class,rr_width:"".concat(H,"px"),rr_height:"".concat(O,"px")}}return h==="iframe"&&!w(s.src)&&(e.contentDocument||(s.rr_src=s.src),delete s.src),{type:g.Element,tagName:h,attributes:s,childNodes:[],isSVG:Qe(e)||void 0,needBlock:x,rootId:T}}function d(e){return e===void 0?"":e.toLowerCase()}function rt(e,t){if(t.comment&&e.type===g.Comment)return!0;if(e.type===g.Element){if(t.script&&(e.tagName==="script"||e.tagName==="link"&&e.attributes.rel==="preload"&&e.attributes.as==="script"||e.tagName==="link"&&e.attributes.rel==="prefetch"&&typeof e.attributes.href=="string"&&e.attributes.href.endsWith(".js")))return!0;if(t.headFavicon&&(e.tagName==="link"&&e.attributes.rel==="shortcut icon"||e.tagName==="meta"&&(d(e.attributes.name).match(/^msapplication-tile(image|color)$/)||d(e.attributes.name)==="application-name"||d(e.attributes.rel)==="icon"||d(e.attributes.rel)==="apple-touch-icon"||d(e.attributes.rel)==="shortcut icon")))return!0;if(e.tagName==="meta"){if(t.headMetaDescKeywords&&d(e.attributes.name).match(/^description|keywords$/))return!0;if(t.headMetaSocial&&(d(e.attributes.property).match(/^(og|twitter|fb):/)||d(e.attributes.name).match(/^(og|twitter):/)||d(e.attributes.name)==="pinterest"))return!0;if(t.headMetaRobots&&(d(e.attributes.name)==="robots"||d(e.attributes.name)==="googlebot"||d(e.attributes.name)==="bingbot"))return!0;if(t.headMetaHttpEquiv&&e.attributes["http-equiv"]!==void 0)return!0;if(t.headMetaAuthorship&&(d(e.attributes.name)==="author"||d(e.attributes.name)==="generator"||d(e.attributes.name)==="framework"||d(e.attributes.name)==="publisher"||d(e.attributes.name)==="progid"||d(e.attributes.property).match(/^article:/)||d(e.attributes.property).match(/^product:/)))return!0;if(t.headMetaVerification&&(d(e.attributes.name)==="google-site-verification"||d(e.attributes.name)==="yandex-verification"||d(e.attributes.name)==="csrf-token"||d(e.attributes.name)==="p:domain_verify"||d(e.attributes.name)==="verify-v1"||d(e.attributes.name)==="verification"||d(e.attributes.name)==="shopify-checkout-api-token"))return!0}}return!1}function Q(e,t){var r=t.doc,i=t.mirror,n=t.blockClass,a=t.blockSelector,c=t.maskTextClass,l=t.maskTextSelector,o=t.skipChild,f=o===void 0?!1:o,u=t.inlineStylesheet,p=u===void 0?!0:u,b=t.maskInputOptions,w=b===void 0?{}:b,k=t.maskTextFn,I=t.maskInputFn,T=t.slimDOMOptions,x=t.dataURLOptions,h=x===void 0?{}:x,s=t.inlineImages,y=s===void 0?!1:s,M=t.recordCanvas,E=M===void 0?!1:M,C=t.onSerialize,m=t.onIframeLoad,P=t.iframeLoadTimeout,_=P===void 0?5e3:P,L=t.onStylesheetLoad,D=t.stylesheetLoadTimeout,A=D===void 0?5e3:D,S=t.keepIframeSrcFn,R=S===void 0?function(){return!1}:S,F=t.newlyAddedElement,U=F===void 0?!1:F,H=t.preserveWhiteSpace,O=H===void 0?!0:H,N=Xe(e,{doc:r,mirror:i,blockClass:n,blockSelector:a,maskTextClass:c,maskTextSelector:l,inlineStylesheet:p,maskInputOptions:w,maskTextFn:k,maskInputFn:I,dataURLOptions:h,inlineImages:y,recordCanvas:E,keepIframeSrcFn:R,newlyAddedElement:U});if(!N)return console.warn(e,"not serialized"),null;var B;i.hasNode(e)?B=i.getId(e):rt(N,T)||!O&&N.type===g.Text&&!N.isStyle&&!N.textContent.replace(/^\s+|\s+$/gm,"").length?B=le:B=Fe();var v=Object.assign(N,{id:B});if(i.add(e,v),B===le)return null;C&&C(e);var J=!f;if(v.type===g.Element){J=J&&!v.needBlock,delete v.needBlock;var ne=e.shadowRoot;ne&&ee(ne)&&(v.isShadowHost=!0)}if((v.type===g.Document||v.type===g.Element)&&J){T.headWhitespace&&v.type===g.Element&&v.tagName==="head"&&(O=!1);for(var ae={doc:r,mirror:i,blockClass:n,blockSelector:a,maskTextClass:c,maskTextSelector:l,skipChild:f,inlineStylesheet:p,maskInputOptions:w,maskTextFn:k,maskInputFn:I,slimDOMOptions:T,dataURLOptions:h,inlineImages:y,recordCanvas:E,preserveWhiteSpace:O,onSerialize:C,onIframeLoad:m,iframeLoadTimeout:_,onStylesheetLoad:L,stylesheetLoadTimeout:A,keepIframeSrcFn:R},Y=0,oe=Array.from(e.childNodes);Y<oe.length;Y++){var V=oe[Y],W=Q(V,ae);W&&v.childNodes.push(W)}if(xe(e)&&e.shadowRoot)for(var X=0,se=Array.from(e.shadowRoot.childNodes);X<se.length;X++){var V=se[X],W=Q(V,ae);W&&(ee(e.shadowRoot)&&(W.isShadow=!0),v.childNodes.push(W))}}return e.parentNode&&Ee(e.parentNode)&&ee(e.parentNode)&&(v.isShadow=!0),v.type===g.Element&&v.tagName==="iframe"&&Ye(e,function(){var G=e.contentDocument;if(G&&m){var ce=Q(G,{doc:G,mirror:i,blockClass:n,blockSelector:a,maskTextClass:c,maskTextSelector:l,skipChild:!1,inlineStylesheet:p,maskInputOptions:w,maskTextFn:k,maskInputFn:I,slimDOMOptions:T,dataURLOptions:h,inlineImages:y,recordCanvas:E,preserveWhiteSpace:O,onSerialize:C,onIframeLoad:m,iframeLoadTimeout:_,onStylesheetLoad:L,stylesheetLoadTimeout:A,keepIframeSrcFn:R});ce&&m(e,ce)}},_),v.type===g.Element&&v.tagName==="link"&&v.attributes.rel==="stylesheet"&&Ve(e,function(){if(L){var G=Q(e,{doc:r,mirror:i,blockClass:n,blockSelector:a,maskTextClass:c,maskTextSelector:l,skipChild:!1,inlineStylesheet:p,maskInputOptions:w,maskTextFn:k,maskInputFn:I,slimDOMOptions:T,dataURLOptions:h,inlineImages:y,recordCanvas:E,preserveWhiteSpace:O,onSerialize:C,onIframeLoad:m,iframeLoadTimeout:_,onStylesheetLoad:L,stylesheetLoadTimeout:A,keepIframeSrcFn:R});G&&L(e,G)}},A),v}function de(e,t){var r=t||{},i=r.mirror,n=i===void 0?new Re:i,a=r.blockClass,c=a===void 0?"rr-block":a,l=r.blockSelector,o=l===void 0?null:l,f=r.maskTextClass,u=f===void 0?"rr-mask":f,p=r.maskTextSelector,b=p===void 0?null:p,w=r.inlineStylesheet,k=w===void 0?!0:w,I=r.inlineImages,T=I===void 0?!1:I,x=r.recordCanvas,h=x===void 0?!1:x,s=r.maskAllInputs,y=s===void 0?!1:s,M=r.maskTextFn,E=r.maskInputFn,C=r.slimDOM,m=C===void 0?!1:C,P=r.dataURLOptions,_=r.preserveWhiteSpace,L=r.onSerialize,D=r.onIframeLoad,A=r.iframeLoadTimeout,S=r.onStylesheetLoad,R=r.stylesheetLoadTimeout,F=r.keepIframeSrcFn,U=F===void 0?function(){return!1}:F,H=y===!0?{color:!0,date:!0,"datetime-local":!0,email:!0,month:!0,number:!0,range:!0,search:!0,tel:!0,text:!0,time:!0,url:!0,week:!0,textarea:!0,select:!0,password:!0}:y===!1?{password:!0}:y,O=m===!0||m==="all"?{script:!0,comment:!0,headFavicon:!0,headWhitespace:!0,headMetaDescKeywords:m==="all",headMetaSocial:!0,headMetaRobots:!0,headMetaHttpEquiv:!0,headMetaAuthorship:!0,headMetaVerification:!0}:m===!1?{}:m;return Q(e,{doc:e,mirror:n,blockClass:c,blockSelector:o,maskTextClass:u,maskTextSelector:b,skipChild:!1,inlineStylesheet:k,maskInputOptions:H,maskTextFn:M,maskInputFn:E,slimDOMOptions:O,dataURLOptions:P,inlineImages:T,recordCanvas:h,preserveWhiteSpace:_,onSerialize:L,onIframeLoad:D,iframeLoadTimeout:A,onStylesheetLoad:S,stylesheetLoadTimeout:R,keepIframeSrcFn:U,newlyAddedElement:!1})}var it=/([^\\]):hover/,st=new RegExp(it.source,"g");function q(){return typeof crypto<"u"&&crypto.randomUUID?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{let t=Math.random()*16|0;return(e==="x"?t:t&3|8).toString(16)})}function he(){let e="_krypton_sid";if(typeof sessionStorage<"u"){let t=sessionStorage.getItem(e);return t||(t=q(),sessionStorage.setItem(e,t)),t}return q()}function pe(){let e="_krypton_did";if(typeof localStorage<"u"){let t=localStorage.getItem(e);return t||(t=q(),localStorage.setItem(e,t)),t}return q()}function me(){if(typeof window>"u")return{};let e=new URLSearchParams(window.location.search),t={};for(let r of["utm_source","utm_medium","utm_campaign","utm_term","utm_content"]){let i=e.get(r);i&&(t[r]=i)}return t}function ve(){if(typeof window>"u")return"unknown";let e=window.innerWidth;return e<768?"mobile":e<1024?"tablet":"desktop"}function ge(e){if(e.id)return`#${e.id}`;let t=[],r=e;for(;r&&r!==document.body;){let i=r.tagName.toLowerCase();if(r.id){t.unshift(`#${r.id}`);break}if(r.className&&typeof r.className=="string"){let n=r.className.trim().split(/\s+/).slice(0,2).join(".");n&&(i+=`.${n}`)}t.unshift(i),r=r.parentElement}return t.join(" > ")}var K=class{constructor(t){this.eventQueue=[];this.heatmapQueue=[];this.flushTimer=null;this.consentGiven=!1;this.initialized=!1;this.lastSnapshotUrl=null;this.serverConfig=null;this.configFetched=!1;this.config={autoPageview:!0,heatmap:!1,consentRequired:!1,flushInterval:5e3,batchSize:20,...t},this.distinctId=pe(),this.sessionId=he(),this.config.consentRequired||(this.consentGiven=!0),this.init()}init(){this.initialized||(this.initialized=!0,this.fetchConfig().then(()=>this.setupTracking()))}async fetchConfig(){if(typeof window>"u")return;let t=`_krypton_config_${this.config.apiKey}`,r=sessionStorage.getItem(t);if(r)try{let i=JSON.parse(r);if(i._ts&&Date.now()-i._ts<300*1e3){this.serverConfig=i,this.configFetched=!0;return}}catch{}try{let i=await fetch(`${this.config.endpoint}/api/v1/config?api_key=${encodeURIComponent(this.config.apiKey)}`);if(i.ok){let n=await i.json();this.serverConfig=n,this.configFetched=!0,sessionStorage.setItem(t,JSON.stringify({...n,_ts:Date.now()}))}}catch{}}setupTracking(){if(this.flushTimer=setInterval(()=>this.flush(),this.config.flushInterval),typeof window<"u"){window.addEventListener("beforeunload",()=>this.flush()),this.config.autoPageview&&this.consentGiven&&this.trackPageview();let t=this.config.heatmap&&(!this.configFetched||this.serverConfig?.heatmaps_enabled),r=history.pushState;history.pushState=(...i)=>{r.apply(history,i),this.config.autoPageview&&this.consentGiven&&setTimeout(()=>this.trackPageview(),0),t&&this.consentGiven&&setTimeout(()=>this.captureSnapshot(),0)},window.addEventListener("popstate",()=>{this.config.autoPageview&&this.consentGiven&&setTimeout(()=>this.trackPageview(),0),t&&this.consentGiven&&setTimeout(()=>this.captureSnapshot(),0)}),t&&this.consentGiven&&this.setupHeatmap()}}grantConsent(){this.consentGiven=!0,this.config.autoPageview&&this.trackPageview(),this.config.heatmap&&(!this.configFetched||this.serverConfig?.heatmaps_enabled)&&this.setupHeatmap()}revokeConsent(){this.consentGiven=!1,this.eventQueue=[],this.heatmapQueue=[]}identify(t){this.distinctId=t,typeof localStorage<"u"&&localStorage.setItem("_krypton_did",t)}trackPageview(t){this.consentGiven&&this.track("$pageview",{...t})}track(t,r){if(!this.consentGiven)return;let i=me(),n={project_id:this.config.apiKey,distinct_id:this.distinctId,event_name:t,timestamp:new Date().toISOString(),properties:r,page_url:typeof window<"u"?window.location.href:"",page_title:typeof document<"u"?document.title:"",referrer:typeof document<"u"?document.referrer:"",utm_source:i.utm_source||"",utm_medium:i.utm_medium||"",utm_campaign:i.utm_campaign||"",utm_term:i.utm_term||"",utm_content:i.utm_content||"",device_type:ve(),browser:this.getBrowser(),screen_width:typeof window<"u"?window.screen.width:0,screen_height:typeof window<"u"?window.screen.height:0,session_id:this.sessionId};this.eventQueue.push(n),this.eventQueue.length>=this.config.batchSize&&this.flush()}async flush(){await Promise.all([this.flushEvents(),this.flushHeatmapEvents()])}shutdown(){this.flushTimer&&(clearInterval(this.flushTimer),this.flushTimer=null),this.flush()}async flushEvents(){if(this.eventQueue.length===0)return;let t=this.eventQueue.splice(0,this.eventQueue.length),r={api_key:this.config.apiKey,events:t};try{await fetch(`${this.config.endpoint}/api/v1/ingest/batch`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(r),keepalive:!0})}catch{this.eventQueue.length<this.config.batchSize*5&&this.eventQueue.unshift(...t)}}async flushHeatmapEvents(){if(this.heatmapQueue.length===0)return;let t=this.heatmapQueue.splice(0,this.heatmapQueue.length),r={api_key:this.config.apiKey,events:t};try{await fetch(`${this.config.endpoint}/api/v1/heatmap`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(r),keepalive:!0})}catch{this.heatmapQueue.length<this.config.batchSize*5&&this.heatmapQueue.unshift(...t)}}captureSnapshot(){if(typeof window>"u"||typeof document>"u")return;let t=window.location.href;this.lastSnapshotUrl!==t&&(this.lastSnapshotUrl=t,setTimeout(()=>{try{let r=de(document,{maskAllInputs:!0,blockSelector:"[data-krypton-block]",inlineStylesheet:!0});if(!r)return;let i=JSON.stringify(r),n={api_key:this.config.apiKey,page_url:t,snapshot:i,viewport_width:window.innerWidth,viewport_height:window.innerHeight,page_width:document.documentElement.scrollWidth,page_height:document.documentElement.scrollHeight,timestamp:new Date().toISOString()};fetch(`${this.config.endpoint}/api/v1/snapshot`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(n),keepalive:!0}).catch(()=>{})}catch{}},1e3))}setupHeatmap(){if(typeof window>"u")return;this.captureSnapshot(),document.addEventListener("click",i=>{if(!this.consentGiven)return;let n=i.target;this.heatmapQueue.push({project_id:this.config.apiKey,distinct_id:this.distinctId,session_id:this.sessionId,timestamp:new Date().toISOString(),page_url:window.location.href,interaction_type:"click",x:i.clientX+window.scrollX,y:i.clientY+window.scrollY,viewport_width:window.innerWidth,viewport_height:window.innerHeight,page_width:document.documentElement.scrollWidth,page_height:document.documentElement.scrollHeight,selector:ge(n)})});let t=0,r=null;window.addEventListener("scroll",()=>{if(!this.consentGiven)return;let i=window.scrollY||document.documentElement.scrollTop,n=document.documentElement.scrollHeight-window.innerHeight,a=n>0?i/n*100:0;a>t&&(t=a),r&&clearTimeout(r),r=setTimeout(()=>{this.heatmapQueue.push({project_id:this.config.apiKey,distinct_id:this.distinctId,session_id:this.sessionId,timestamp:new Date().toISOString(),page_url:window.location.href,interaction_type:"scroll",scroll_depth:t,viewport_width:window.innerWidth,viewport_height:window.innerHeight,page_width:document.documentElement.scrollWidth,page_height:document.documentElement.scrollHeight})},500)})}getBrowser(){if(typeof navigator>"u")return"unknown";let t=navigator.userAgent;return t.includes("Firefox")?"Firefox":t.includes("Edg")?"Edge":t.includes("Chrome")?"Chrome":t.includes("Safari")?"Safari":"Other"}};function ye(e){return new K(e)}var we={Krypton:K,init:ye};typeof window<"u"&&(window.KryptonAnalytics=we);var nt=we;return Te(at);})();
|
|
1
|
+
"use strict";var KryptonAnalytics=(()=>{var Z=Object.defineProperty;var we=Object.getOwnPropertyDescriptor;var Se=Object.getOwnPropertyNames;var be=Object.prototype.hasOwnProperty;var Ce=(e,t)=>{for(var r in t)Z(e,r,{get:t[r],enumerable:!0})},xe=(e,t,r,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of Se(t))!be.call(e,n)&&n!==r&&Z(e,n,{get:()=>t[n],enumerable:!(i=we(t,n))||i.enumerable});return e};var Ie=e=>xe(Z({},"__esModule",{value:!0}),e);var at={};Ce(at,{Krypton:()=>q,default:()=>nt,init:()=>ye});var v;(function(e){e[e.Document=0]="Document",e[e.DocumentType=1]="DocumentType",e[e.Element=2]="Element",e[e.Text=3]="Text",e[e.CDATA=4]="CDATA",e[e.Comment=5]="Comment"})(v||(v={}));function Te(e){return e.nodeType===e.ELEMENT_NODE}function Ee(e){var t=e?.host;return t?.shadowRoot===e}function ee(e){return Object.prototype.toString.call(e)==="[object ShadowRoot]"}function Le(e){return e.includes(" background-clip: text;")&&!e.includes(" -webkit-background-clip: text;")&&(e=e.replace(" background-clip: text;"," -webkit-background-clip: text; background-clip: text;")),e}function te(e){try{var t=e.rules||e.cssRules;return t?Le(Array.from(t).map(Re).join("")):null}catch{return null}}function Re(e){var t=e.cssText;if(_e(e))try{t=te(e.styleSheet)||t}catch{}return t}function _e(e){return"styleSheet"in e}var Ne=(function(){function e(){this.idNodeMap=new Map,this.nodeMetaMap=new WeakMap}return e.prototype.getId=function(t){var r;if(!t)return-1;var i=(r=this.getMeta(t))===null||r===void 0?void 0:r.id;return i??-1},e.prototype.getNode=function(t){return this.idNodeMap.get(t)||null},e.prototype.getIds=function(){return Array.from(this.idNodeMap.keys())},e.prototype.getMeta=function(t){return this.nodeMetaMap.get(t)||null},e.prototype.removeNodeFromMap=function(t){var r=this,i=this.getId(t);this.idNodeMap.delete(i),t.childNodes&&t.childNodes.forEach(function(n){return r.removeNodeFromMap(n)})},e.prototype.has=function(t){return this.idNodeMap.has(t)},e.prototype.hasNode=function(t){return this.nodeMetaMap.has(t)},e.prototype.add=function(t,r){var i=r.id;this.idNodeMap.set(i,t),this.nodeMetaMap.set(t,r)},e.prototype.replace=function(t,r){var i=this.getNode(t);if(i){var n=this.nodeMetaMap.get(i);n&&this.nodeMetaMap.set(r,n)}this.idNodeMap.set(t,r)},e.prototype.reset=function(){this.idNodeMap=new Map,this.nodeMetaMap=new WeakMap},e})();function Oe(e){var t=e.maskInputOptions,r=e.tagName,i=e.type,n=e.value,a=e.maskInputFn,c=n||"";return(t[r.toLowerCase()]||t[i])&&(a?c=a(c):c="*".repeat(c.length)),c}var le="__rrweb_original__";function Me(e){var t=e.getContext("2d");if(!t)return!0;for(var r=50,i=0;i<e.width;i+=r)for(var n=0;n<e.height;n+=r){var a=t.getImageData,c=le in a?a[le]:a,u=new Uint32Array(c.call(t,i,n,Math.min(r,e.width-i),Math.min(r,e.height-n)).data.buffer);if(u.some(function(o){return o!==0}))return!1}return!0}var Ae=1,De=new RegExp("[^a-z0-9-_:]"),ue=-2;function Fe(){return Ae++}function Pe(e){if(e instanceof HTMLFormElement)return"form";var t=e.tagName.toLowerCase().trim();return De.test(t)?"div":t}function He(e){return e.cssRules?Array.from(e.cssRules).map(function(t){return t.cssText||""}).join(""):""}function Ue(e){var t="";return e.indexOf("//")>-1?t=e.split("/").slice(0,3).join("/"):t=e.split("/")[0],t=t.split("?")[0],t}var z,fe,We=/url\((?:(')([^']*)'|(")(.*?)"|([^)]*))\)/gm,Ke=/^(?!www\.|(?:http|ftp)s?:\/\/|[A-Za-z]:\\|\/\/|#).*/,Be=/^(data:)([^,]*),(.*)/i;function $(e,t){return(e||"").replace(We,function(r,i,n,a,c,u){var o=n||c||u,f=i||a||"";if(!o)return r;if(!Ke.test(o)||Be.test(o))return"url(".concat(f).concat(o).concat(f,")");if(o[0]==="/")return"url(".concat(f).concat(Ue(t)+o).concat(f,")");var l=t.split("/"),h=o.split("/");l.pop();for(var b=0,k=h;b<k.length;b++){var w=k[b];w!=="."&&(w===".."?l.pop():l.push(w))}return"url(".concat(f).concat(l.join("/")).concat(f,")")})}var ze=/^[^ \t\n\r\u000c]+/,je=/^[, \t\n\r\u000c]+/;function qe(e,t){if(t.trim()==="")return t;var r=0;function i(f){var l,h=f.exec(t.substring(r));return h?(l=h[0],r+=l.length,l):""}for(var n=[];i(je),!(r>=t.length);){var a=i(ze);if(a.slice(-1)===",")a=j(e,a.substring(0,a.length-1)),n.push(a);else{var c="";a=j(e,a);for(var u=!1;;){var o=t.charAt(r);if(o===""){n.push((a+c).trim());break}else if(u)o===")"&&(u=!1);else if(o===","){r+=1,n.push((a+c).trim());break}else o==="("&&(u=!0);c+=o,r+=1}}}return n.join(", ")}function j(e,t){if(!t||t.trim()==="")return t;var r=e.createElement("a");return r.href=t,r.href}function Ge(e){return!!(e.tagName==="svg"||e.ownerSVGElement)}function ie(){var e=document.createElement("a");return e.href="",e.href}function Qe(e,t,r,i){return r==="src"||r==="href"&&i&&!(t==="use"&&i[0]==="#")||r==="xlink:href"&&i&&i[0]!=="#"||r==="background"&&i&&(t==="table"||t==="td"||t==="th")?j(e,i):r==="srcset"&&i?qe(e,i):r==="style"&&i?$(i,ie()):t==="object"&&r==="data"&&i?j(e,i):i}function $e(e,t,r){if(typeof t=="string"){if(e.classList.contains(t))return!0}else for(var i=e.classList.length;i--;){var n=e.classList[i];if(t.test(n))return!0}return r?e.matches(r):!1}function re(e,t,r){if(!e)return!1;if(e.nodeType!==e.ELEMENT_NODE)return r?re(e.parentNode,t,r):!1;for(var i=e.classList.length;i--;){var n=e.classList[i];if(t.test(n))return!0}return r?re(e.parentNode,t,r):!1}function Je(e,t,r){var i=e.nodeType===e.ELEMENT_NODE?e:e.parentElement;if(i===null)return!1;if(typeof t=="string"){if(i.classList.contains(t)||i.closest(".".concat(t)))return!0}else if(re(i,t,!0))return!0;return!!(r&&(i.matches(r)||i.closest(r)))}function Ve(e,t,r){var i=e.contentWindow;if(i){var n=!1,a;try{a=i.document.readyState}catch{return}if(a!=="complete"){var c=setTimeout(function(){n||(t(),n=!0)},r);e.addEventListener("load",function(){clearTimeout(c),n=!0,t()});return}var u="about:blank";if(i.location.href!==u||e.src===u||e.src==="")return setTimeout(t,0),e.addEventListener("load",t);e.addEventListener("load",t)}}function Ye(e,t,r){var i=!1,n;try{n=e.sheet}catch{return}if(!n){var a=setTimeout(function(){i||(t(),i=!0)},r);e.addEventListener("load",function(){clearTimeout(a),i=!0,t()})}}function Xe(e,t){var r=t.doc,i=t.mirror,n=t.blockClass,a=t.blockSelector,c=t.maskTextClass,u=t.maskTextSelector,o=t.inlineStylesheet,f=t.maskInputOptions,l=f===void 0?{}:f,h=t.maskTextFn,b=t.maskInputFn,k=t.dataURLOptions,w=k===void 0?{}:k,x=t.inlineImages,I=t.recordCanvas,T=t.keepIframeSrcFn,p=t.newlyAddedElement,s=p===void 0?!1:p,y=Ze(r,i);switch(e.nodeType){case e.DOCUMENT_NODE:return e.compatMode!=="CSS1Compat"?{type:v.Document,childNodes:[],compatMode:e.compatMode}:{type:v.Document,childNodes:[]};case e.DOCUMENT_TYPE_NODE:return{type:v.DocumentType,name:e.name,publicId:e.publicId,systemId:e.systemId,rootId:y};case e.ELEMENT_NODE:return tt(e,{doc:r,blockClass:n,blockSelector:a,inlineStylesheet:o,maskInputOptions:l,maskInputFn:b,dataURLOptions:w,inlineImages:x,recordCanvas:I,keepIframeSrcFn:T,newlyAddedElement:s,rootId:y});case e.TEXT_NODE:return et(e,{maskTextClass:c,maskTextSelector:u,maskTextFn:h,rootId:y});case e.CDATA_SECTION_NODE:return{type:v.CDATA,textContent:"",rootId:y};case e.COMMENT_NODE:return{type:v.Comment,textContent:e.textContent||"",rootId:y};default:return!1}}function Ze(e,t){if(t.hasNode(e)){var r=t.getId(e);return r===1?void 0:r}}function et(e,t){var r,i=t.maskTextClass,n=t.maskTextSelector,a=t.maskTextFn,c=t.rootId,u=e.parentNode&&e.parentNode.tagName,o=e.textContent,f=u==="STYLE"?!0:void 0,l=u==="SCRIPT"?!0:void 0;if(f&&o){try{e.nextSibling||e.previousSibling||!((r=e.parentNode.sheet)===null||r===void 0)&&r.cssRules&&(o=He(e.parentNode.sheet))}catch(h){console.warn("Cannot get CSS styles from text's parentNode. Error: ".concat(h),e)}o=$(o,ie())}return l&&(o="SCRIPT_PLACEHOLDER"),!f&&!l&&o&&Je(e,i,n)&&(o=a?a(o):o.replace(/[\S]/g,"*")),{type:v.Text,textContent:o||"",isStyle:f,rootId:c}}function tt(e,t){for(var r=t.doc,i=t.blockClass,n=t.blockSelector,a=t.inlineStylesheet,c=t.maskInputOptions,u=c===void 0?{}:c,o=t.maskInputFn,f=t.dataURLOptions,l=f===void 0?{}:f,h=t.inlineImages,b=t.recordCanvas,k=t.keepIframeSrcFn,w=t.newlyAddedElement,x=w===void 0?!1:w,I=t.rootId,T=$e(e,i,n),p=Pe(e),s={},y=e.attributes.length,M=0;M<y;M++){var E=e.attributes[M];s[E.name]=Qe(r,p,E.name,E.value)}if(p==="link"&&a){var C=Array.from(r.styleSheets).find(function(R){return R.href===e.href}),m=null;C&&(m=te(C)),m&&(delete s.rel,delete s.href,s._cssText=$(m,C.href))}if(p==="style"&&e.sheet&&!(e.innerText||e.textContent||"").trim().length){var m=te(e.sheet);m&&(s._cssText=$(m,ie()))}if(p==="input"||p==="textarea"||p==="select"){var P=e.value,_=e.checked;s.type!=="radio"&&s.type!=="checkbox"&&s.type!=="submit"&&s.type!=="button"&&P?s.value=Oe({type:s.type,tagName:p,value:P,maskInputOptions:u,maskInputFn:o}):_&&(s.checked=_)}if(p==="option"&&(e.selected&&!u.select?s.selected=!0:delete s.selected),p==="canvas"&&b){if(e.__context==="2d")Me(e)||(s.rr_dataURL=e.toDataURL(l.type,l.quality));else if(!("__context"in e)){var L=e.toDataURL(l.type,l.quality),A=document.createElement("canvas");A.width=e.width,A.height=e.height;var D=A.toDataURL(l.type,l.quality);L!==D&&(s.rr_dataURL=L)}}if(p==="img"&&h){z||(z=r.createElement("canvas"),fe=z.getContext("2d"));var S=e,N=S.crossOrigin;S.crossOrigin="anonymous";var F=function(){try{z.width=S.naturalWidth,z.height=S.naturalHeight,fe.drawImage(S,0,0),s.rr_dataURL=z.toDataURL(l.type,l.quality)}catch(R){console.warn("Cannot inline img src=".concat(S.currentSrc,"! Error: ").concat(R))}N?s.crossOrigin=N:S.removeAttribute("crossorigin")};S.complete&&S.naturalWidth!==0?F():S.onload=F}if((p==="audio"||p==="video")&&(s.rr_mediaState=e.paused?"paused":"played",s.rr_mediaCurrentTime=e.currentTime),x||(e.scrollLeft&&(s.rr_scrollLeft=e.scrollLeft),e.scrollTop&&(s.rr_scrollTop=e.scrollTop)),T){var U=e.getBoundingClientRect(),W=U.width,O=U.height;s={class:s.class,rr_width:"".concat(W,"px"),rr_height:"".concat(O,"px")}}return p==="iframe"&&!k(s.src)&&(e.contentDocument||(s.rr_src=s.src),delete s.src),{type:v.Element,tagName:p,attributes:s,childNodes:[],isSVG:Ge(e)||void 0,needBlock:T,rootId:I}}function d(e){return e===void 0?"":e.toLowerCase()}function rt(e,t){if(t.comment&&e.type===v.Comment)return!0;if(e.type===v.Element){if(t.script&&(e.tagName==="script"||e.tagName==="link"&&e.attributes.rel==="preload"&&e.attributes.as==="script"||e.tagName==="link"&&e.attributes.rel==="prefetch"&&typeof e.attributes.href=="string"&&e.attributes.href.endsWith(".js")))return!0;if(t.headFavicon&&(e.tagName==="link"&&e.attributes.rel==="shortcut icon"||e.tagName==="meta"&&(d(e.attributes.name).match(/^msapplication-tile(image|color)$/)||d(e.attributes.name)==="application-name"||d(e.attributes.rel)==="icon"||d(e.attributes.rel)==="apple-touch-icon"||d(e.attributes.rel)==="shortcut icon")))return!0;if(e.tagName==="meta"){if(t.headMetaDescKeywords&&d(e.attributes.name).match(/^description|keywords$/))return!0;if(t.headMetaSocial&&(d(e.attributes.property).match(/^(og|twitter|fb):/)||d(e.attributes.name).match(/^(og|twitter):/)||d(e.attributes.name)==="pinterest"))return!0;if(t.headMetaRobots&&(d(e.attributes.name)==="robots"||d(e.attributes.name)==="googlebot"||d(e.attributes.name)==="bingbot"))return!0;if(t.headMetaHttpEquiv&&e.attributes["http-equiv"]!==void 0)return!0;if(t.headMetaAuthorship&&(d(e.attributes.name)==="author"||d(e.attributes.name)==="generator"||d(e.attributes.name)==="framework"||d(e.attributes.name)==="publisher"||d(e.attributes.name)==="progid"||d(e.attributes.property).match(/^article:/)||d(e.attributes.property).match(/^product:/)))return!0;if(t.headMetaVerification&&(d(e.attributes.name)==="google-site-verification"||d(e.attributes.name)==="yandex-verification"||d(e.attributes.name)==="csrf-token"||d(e.attributes.name)==="p:domain_verify"||d(e.attributes.name)==="verify-v1"||d(e.attributes.name)==="verification"||d(e.attributes.name)==="shopify-checkout-api-token"))return!0}}return!1}function Q(e,t){var r=t.doc,i=t.mirror,n=t.blockClass,a=t.blockSelector,c=t.maskTextClass,u=t.maskTextSelector,o=t.skipChild,f=o===void 0?!1:o,l=t.inlineStylesheet,h=l===void 0?!0:l,b=t.maskInputOptions,k=b===void 0?{}:b,w=t.maskTextFn,x=t.maskInputFn,I=t.slimDOMOptions,T=t.dataURLOptions,p=T===void 0?{}:T,s=t.inlineImages,y=s===void 0?!1:s,M=t.recordCanvas,E=M===void 0?!1:M,C=t.onSerialize,m=t.onIframeLoad,P=t.iframeLoadTimeout,_=P===void 0?5e3:P,L=t.onStylesheetLoad,A=t.stylesheetLoadTimeout,D=A===void 0?5e3:A,S=t.keepIframeSrcFn,N=S===void 0?function(){return!1}:S,F=t.newlyAddedElement,U=F===void 0?!1:F,W=t.preserveWhiteSpace,O=W===void 0?!0:W,R=Xe(e,{doc:r,mirror:i,blockClass:n,blockSelector:a,maskTextClass:c,maskTextSelector:u,inlineStylesheet:h,maskInputOptions:k,maskTextFn:w,maskInputFn:x,dataURLOptions:p,inlineImages:y,recordCanvas:E,keepIframeSrcFn:N,newlyAddedElement:U});if(!R)return console.warn(e,"not serialized"),null;var G;i.hasNode(e)?G=i.getId(e):rt(R,I)||!O&&R.type===v.Text&&!R.isStyle&&!R.textContent.replace(/^\s+|\s+$/gm,"").length?G=ue:G=Fe();var g=Object.assign(R,{id:G});if(i.add(e,g),G===ue)return null;C&&C(e);var J=!f;if(g.type===v.Element){J=J&&!g.needBlock,delete g.needBlock;var ne=e.shadowRoot;ne&&ee(ne)&&(g.isShadowHost=!0)}if((g.type===v.Document||g.type===v.Element)&&J){I.headWhitespace&&g.type===v.Element&&g.tagName==="head"&&(O=!1);for(var ae={doc:r,mirror:i,blockClass:n,blockSelector:a,maskTextClass:c,maskTextSelector:u,skipChild:f,inlineStylesheet:h,maskInputOptions:k,maskTextFn:w,maskInputFn:x,slimDOMOptions:I,dataURLOptions:p,inlineImages:y,recordCanvas:E,preserveWhiteSpace:O,onSerialize:C,onIframeLoad:m,iframeLoadTimeout:_,onStylesheetLoad:L,stylesheetLoadTimeout:D,keepIframeSrcFn:N},V=0,oe=Array.from(e.childNodes);V<oe.length;V++){var Y=oe[V],K=Q(Y,ae);K&&g.childNodes.push(K)}if(Te(e)&&e.shadowRoot)for(var X=0,se=Array.from(e.shadowRoot.childNodes);X<se.length;X++){var Y=se[X],K=Q(Y,ae);K&&(ee(e.shadowRoot)&&(K.isShadow=!0),g.childNodes.push(K))}}return e.parentNode&&Ee(e.parentNode)&&ee(e.parentNode)&&(g.isShadow=!0),g.type===v.Element&&g.tagName==="iframe"&&Ve(e,function(){var B=e.contentDocument;if(B&&m){var ce=Q(B,{doc:B,mirror:i,blockClass:n,blockSelector:a,maskTextClass:c,maskTextSelector:u,skipChild:!1,inlineStylesheet:h,maskInputOptions:k,maskTextFn:w,maskInputFn:x,slimDOMOptions:I,dataURLOptions:p,inlineImages:y,recordCanvas:E,preserveWhiteSpace:O,onSerialize:C,onIframeLoad:m,iframeLoadTimeout:_,onStylesheetLoad:L,stylesheetLoadTimeout:D,keepIframeSrcFn:N});ce&&m(e,ce)}},_),g.type===v.Element&&g.tagName==="link"&&g.attributes.rel==="stylesheet"&&Ye(e,function(){if(L){var B=Q(e,{doc:r,mirror:i,blockClass:n,blockSelector:a,maskTextClass:c,maskTextSelector:u,skipChild:!1,inlineStylesheet:h,maskInputOptions:k,maskTextFn:w,maskInputFn:x,slimDOMOptions:I,dataURLOptions:p,inlineImages:y,recordCanvas:E,preserveWhiteSpace:O,onSerialize:C,onIframeLoad:m,iframeLoadTimeout:_,onStylesheetLoad:L,stylesheetLoadTimeout:D,keepIframeSrcFn:N});B&&L(e,B)}},D),g}function de(e,t){var r=t||{},i=r.mirror,n=i===void 0?new Ne:i,a=r.blockClass,c=a===void 0?"rr-block":a,u=r.blockSelector,o=u===void 0?null:u,f=r.maskTextClass,l=f===void 0?"rr-mask":f,h=r.maskTextSelector,b=h===void 0?null:h,k=r.inlineStylesheet,w=k===void 0?!0:k,x=r.inlineImages,I=x===void 0?!1:x,T=r.recordCanvas,p=T===void 0?!1:T,s=r.maskAllInputs,y=s===void 0?!1:s,M=r.maskTextFn,E=r.maskInputFn,C=r.slimDOM,m=C===void 0?!1:C,P=r.dataURLOptions,_=r.preserveWhiteSpace,L=r.onSerialize,A=r.onIframeLoad,D=r.iframeLoadTimeout,S=r.onStylesheetLoad,N=r.stylesheetLoadTimeout,F=r.keepIframeSrcFn,U=F===void 0?function(){return!1}:F,W=y===!0?{color:!0,date:!0,"datetime-local":!0,email:!0,month:!0,number:!0,range:!0,search:!0,tel:!0,text:!0,time:!0,url:!0,week:!0,textarea:!0,select:!0,password:!0}:y===!1?{password:!0}:y,O=m===!0||m==="all"?{script:!0,comment:!0,headFavicon:!0,headWhitespace:!0,headMetaDescKeywords:m==="all",headMetaSocial:!0,headMetaRobots:!0,headMetaHttpEquiv:!0,headMetaAuthorship:!0,headMetaVerification:!0}:m===!1?{}:m;return Q(e,{doc:e,mirror:n,blockClass:c,blockSelector:o,maskTextClass:l,maskTextSelector:b,skipChild:!1,inlineStylesheet:w,maskInputOptions:W,maskTextFn:M,maskInputFn:E,slimDOMOptions:O,dataURLOptions:P,inlineImages:I,recordCanvas:p,preserveWhiteSpace:_,onSerialize:L,onIframeLoad:A,iframeLoadTimeout:D,onStylesheetLoad:S,stylesheetLoadTimeout:N,keepIframeSrcFn:U,newlyAddedElement:!1})}var it=/([^\\]):hover/,st=new RegExp(it.source,"g");function H(){return typeof crypto<"u"&&crypto.randomUUID?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{let t=Math.random()*16|0;return(e==="x"?t:t&3|8).toString(16)})}function pe(){let e="_krypton_sid";if(typeof sessionStorage<"u"){let t=sessionStorage.getItem(e);return t||(t=H(),sessionStorage.setItem(e,t)),t}return H()}function he(){let e="_krypton_did";if(typeof localStorage<"u"){let t=localStorage.getItem(e);return t||(t=H(),localStorage.setItem(e,t)),t}return H()}function me(){if(typeof window>"u")return{};let e=new URLSearchParams(window.location.search),t={};for(let r of["utm_source","utm_medium","utm_campaign","utm_term","utm_content"]){let i=e.get(r);i&&(t[r]=i)}return t}function ge(){if(typeof window>"u")return"unknown";let e=window.innerWidth;return e<768?"mobile":e<1024?"tablet":"desktop"}function ve(e){if(e.id)return`#${e.id}`;let t=[],r=e;for(;r&&r!==document.body;){let i=r.tagName.toLowerCase();if(r.id){t.unshift(`#${r.id}`);break}if(r.className&&typeof r.className=="string"){let n=r.className.trim().split(/\s+/).slice(0,2).join(".");n&&(i+=`.${n}`)}t.unshift(i),r=r.parentElement}return t.join(" > ")}var q=class{constructor(t){this.eventQueue=[];this.heatmapQueue=[];this.flushTimer=null;this.initialized=!1;this.lastSnapshotUrl=null;this.heatmapSetup=!1;this.geoRequested=!1;this.geoContext=null;this.serverConfig=null;this.configFetched=!1;this.config={autoPageview:!0,heatmap:!1,consentRequired:!1,showConsentBanner:!1,consentCategories:{},flushInterval:5e3,batchSize:20,...t},this.distinctId=H(),this.sessionId=H(),this.consent=this.resolveInitialConsent(),this.canTrackAnalytics()&&this.promotePersistentIds(),this.init()}init(){this.initialized||(this.initialized=!0,this.fetchConfig().then(()=>{this.setupTracking(),this.config.consentRequired&&this.config.showConsentBanner&&!this.hasStoredConsent()&&this.showConsentBanner()}))}resolveInitialConsent(){let t=this.loadStoredConsent();return t||{...this.config.consentRequired?{analytics:!1,heatmaps:!1,geo:!1}:{analytics:!0,heatmaps:!!this.config.heatmap,geo:!1},...this.config.consentCategories}}consentStorageKey(){return`_krypton_consent_${this.config.apiKey}`}hasStoredConsent(){return typeof localStorage>"u"?!1:!!localStorage.getItem(this.consentStorageKey())}loadStoredConsent(){if(typeof localStorage>"u")return null;let t=localStorage.getItem(this.consentStorageKey());if(!t)return null;try{let r=JSON.parse(t);return{analytics:!!r.analytics,heatmaps:!!r.heatmaps,geo:!!r.geo}}catch{return null}}persistConsent(){typeof localStorage>"u"||localStorage.setItem(this.consentStorageKey(),JSON.stringify(this.consent))}promotePersistentIds(){this.distinctId=he(),this.sessionId=pe()}canTrackAnalytics(){return!!this.consent.analytics}isHeatmapFeatureEnabled(){return!this.config.heatmap||this.configFetched&&!this.serverConfig?.heatmaps_enabled?!1:!!this.consent.heatmaps}async fetchConfig(){if(typeof window>"u")return;let t=`_krypton_config_${this.config.apiKey}`,r=sessionStorage.getItem(t);if(r)try{let i=JSON.parse(r);if(i._ts&&Date.now()-i._ts<300*1e3){this.serverConfig=i,this.configFetched=!0;return}}catch{}try{let i=await fetch(`${this.config.endpoint}/api/v1/config?api_key=${encodeURIComponent(this.config.apiKey)}`);if(i.ok){let n=await i.json();this.serverConfig=n,this.configFetched=!0,sessionStorage.setItem(t,JSON.stringify({...n,_ts:Date.now()}))}}catch{}}setupTracking(){if(this.flushTimer=setInterval(()=>this.flush(),this.config.flushInterval),typeof window>"u")return;window.addEventListener("beforeunload",()=>this.flush()),this.config.autoPageview&&this.canTrackAnalytics()&&this.trackPageview();let t=history.pushState;history.pushState=(...i)=>{t.apply(history,i),this.config.autoPageview&&this.canTrackAnalytics()&&setTimeout(()=>this.trackPageview(),0),this.isHeatmapFeatureEnabled()&&setTimeout(()=>this.captureSnapshot(),0)};let r=history.replaceState;history.replaceState=(...i)=>{r.apply(history,i),this.config.autoPageview&&this.canTrackAnalytics()&&setTimeout(()=>this.trackPageview(),0),this.isHeatmapFeatureEnabled()&&setTimeout(()=>this.captureSnapshot(),0)},window.addEventListener("popstate",()=>{this.config.autoPageview&&this.canTrackAnalytics()&&setTimeout(()=>this.trackPageview(),0),this.isHeatmapFeatureEnabled()&&setTimeout(()=>this.captureSnapshot(),0)}),this.isHeatmapFeatureEnabled()&&this.setupHeatmap(),this.consent.geo&&this.captureGeoOnce()}showConsentBanner(){if(typeof document>"u"||document.getElementById("krypton-consent-banner"))return;let t=document.createElement("div");t.id="krypton-consent-banner",t.style.cssText=["position:fixed","left:16px","right:16px","bottom:16px","z-index:2147483647","max-width:720px","margin:0 auto","background:#111827","color:#f9fafb","border-radius:12px","padding:16px","box-shadow:0 12px 30px rgba(0,0,0,0.35)","font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif","font-size:14px","line-height:1.4"].join(";");let r=a=>a?"checked":"";t.innerHTML=`
|
|
2
|
+
<div style="font-weight:600;margin-bottom:6px">Privacy preferences</div>
|
|
3
|
+
<div style="opacity:0.9;margin-bottom:10px">Choose what data you allow us to collect.</div>
|
|
4
|
+
<label style="display:flex;gap:8px;align-items:flex-start;margin:6px 0">
|
|
5
|
+
<input type="checkbox" id="krypton-consent-analytics" ${r(this.consent.analytics)} />
|
|
6
|
+
<span><strong>Analytics</strong> (pageviews and custom events)</span>
|
|
7
|
+
</label>
|
|
8
|
+
<label style="display:flex;gap:8px;align-items:flex-start;margin:6px 0">
|
|
9
|
+
<input type="checkbox" id="krypton-consent-heatmaps" ${r(this.consent.heatmaps)} />
|
|
10
|
+
<span><strong>Heatmaps</strong> (click and scroll interaction maps)</span>
|
|
11
|
+
</label>
|
|
12
|
+
<label style="display:flex;gap:8px;align-items:flex-start;margin:6px 0 12px 0">
|
|
13
|
+
<input type="checkbox" id="krypton-consent-geo" ${r(this.consent.geo)} />
|
|
14
|
+
<span><strong>Geo location</strong> (browser geolocation if available)</span>
|
|
15
|
+
</label>
|
|
16
|
+
<div style="display:flex;gap:8px;flex-wrap:wrap">
|
|
17
|
+
<button id="krypton-consent-save" style="border:0;background:#2563eb;color:#fff;padding:8px 12px;border-radius:8px;cursor:pointer">Accept selected</button>
|
|
18
|
+
<button id="krypton-consent-all" style="border:0;background:#16a34a;color:#fff;padding:8px 12px;border-radius:8px;cursor:pointer">Accept all</button>
|
|
19
|
+
<button id="krypton-consent-none" style="border:1px solid #4b5563;background:transparent;color:#f9fafb;padding:8px 12px;border-radius:8px;cursor:pointer">Reject all</button>
|
|
20
|
+
</div>
|
|
21
|
+
`;let i=()=>{t.remove()},n=a=>!!document.getElementById(a)?.checked;t.querySelector("#krypton-consent-save")?.addEventListener("click",()=>{this.setConsent({analytics:n("krypton-consent-analytics"),heatmaps:n("krypton-consent-heatmaps"),geo:n("krypton-consent-geo")}),i()}),t.querySelector("#krypton-consent-all")?.addEventListener("click",()=>{this.setConsent({analytics:!0,heatmaps:!0,geo:!0}),i()}),t.querySelector("#krypton-consent-none")?.addEventListener("click",()=>{this.setConsent({analytics:!1,heatmaps:!1,geo:!1}),i()}),document.body.appendChild(t)}setConsent(t,r=!0){let i={...this.consent};this.consent={analytics:t.analytics??i.analytics,heatmaps:t.heatmaps??i.heatmaps,geo:t.geo??i.geo},r&&this.persistConsent(),!i.analytics&&this.consent.analytics&&(this.promotePersistentIds(),this.config.autoPageview&&this.trackPageview()),i.analytics&&!this.consent.analytics&&(this.eventQueue=[]),!i.heatmaps&&this.isHeatmapFeatureEnabled()&&(this.setupHeatmap(),this.captureSnapshot()),i.heatmaps&&!this.consent.heatmaps&&(this.heatmapQueue=[]),!i.geo&&this.consent.geo&&this.captureGeoOnce()}getConsent(){return{...this.consent}}grantConsent(){this.setConsent({analytics:!0,heatmaps:!0,geo:!0})}revokeConsent(){this.setConsent({analytics:!1,heatmaps:!1,geo:!1}),this.eventQueue=[],this.heatmapQueue=[]}identify(t){this.distinctId=t,typeof localStorage<"u"&&this.canTrackAnalytics()&&localStorage.setItem("_krypton_did",t)}trackPageview(t){this.canTrackAnalytics()&&this.track("$pageview",{...t})}track(t,r){if(!this.canTrackAnalytics())return;let i=me(),n={...r||{}};this.consent.geo&&this.geoContext&&(n.geo=this.geoContext);let a={project_id:this.config.apiKey,distinct_id:this.distinctId,event_name:t,timestamp:new Date().toISOString(),properties:n,page_url:typeof window<"u"?window.location.href:"",page_title:typeof document<"u"?document.title:"",referrer:typeof document<"u"?document.referrer:"",utm_source:i.utm_source||"",utm_medium:i.utm_medium||"",utm_campaign:i.utm_campaign||"",utm_term:i.utm_term||"",utm_content:i.utm_content||"",device_type:ge(),browser:this.getBrowser(),screen_width:typeof window<"u"?window.screen.width:0,screen_height:typeof window<"u"?window.screen.height:0,session_id:this.sessionId};this.eventQueue.push(a),this.eventQueue.length>=this.config.batchSize&&this.flush()}async flush(){await Promise.all([this.flushEvents(),this.flushHeatmapEvents()])}shutdown(){this.flushTimer&&(clearInterval(this.flushTimer),this.flushTimer=null),this.flush()}captureGeoOnce(){this.geoRequested||this.consent.geo&&(typeof navigator>"u"||!navigator.geolocation||(this.geoRequested=!0,navigator.geolocation.getCurrentPosition(t=>{let r=(i,n=3)=>Number(i.toFixed(n));this.geoContext={lat:r(t.coords.latitude),lon:r(t.coords.longitude),accuracy_m:Math.round(t.coords.accuracy),captured_at:new Date().toISOString()}},()=>{},{enableHighAccuracy:!1,maximumAge:600*1e3,timeout:5e3})))}async flushEvents(){if(this.eventQueue.length===0)return;let t=this.eventQueue.splice(0,this.eventQueue.length),r={api_key:this.config.apiKey,events:t};try{await fetch(`${this.config.endpoint}/api/v1/ingest/batch`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(r),keepalive:!0})}catch{this.eventQueue.length<this.config.batchSize*5&&this.eventQueue.unshift(...t)}}async flushHeatmapEvents(){if(this.heatmapQueue.length===0)return;let t=this.heatmapQueue.splice(0,this.heatmapQueue.length),r={api_key:this.config.apiKey,events:t};try{await fetch(`${this.config.endpoint}/api/v1/heatmap`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(r),keepalive:!0})}catch{this.heatmapQueue.length<this.config.batchSize*5&&this.heatmapQueue.unshift(...t)}}captureSnapshot(){if(typeof window>"u"||typeof document>"u"||!this.isHeatmapFeatureEnabled())return;let t=window.location.href;this.lastSnapshotUrl!==t&&(this.lastSnapshotUrl=t,setTimeout(()=>{try{let r=de(document,{maskAllInputs:!0,blockSelector:"[data-krypton-block]",inlineStylesheet:!0});if(!r)return;let i=JSON.stringify(r),n={api_key:this.config.apiKey,page_url:t,snapshot:i,viewport_width:window.innerWidth,viewport_height:window.innerHeight,page_width:document.documentElement.scrollWidth,page_height:document.documentElement.scrollHeight,timestamp:new Date().toISOString()};fetch(`${this.config.endpoint}/api/v1/snapshot`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(n),keepalive:!0}).catch(()=>{})}catch{}},1e3))}setupHeatmap(){if(typeof window>"u"||this.heatmapSetup)return;this.heatmapSetup=!0,this.captureSnapshot(),document.addEventListener("click",i=>{if(!this.isHeatmapFeatureEnabled())return;let n=i.target;this.heatmapQueue.push({project_id:this.config.apiKey,distinct_id:this.distinctId,session_id:this.sessionId,timestamp:new Date().toISOString(),page_url:window.location.href,interaction_type:"click",x:i.clientX+window.scrollX,y:i.clientY+window.scrollY,viewport_width:window.innerWidth,viewport_height:window.innerHeight,page_width:document.documentElement.scrollWidth,page_height:document.documentElement.scrollHeight,selector:ve(n)})});let t=0,r=null;window.addEventListener("scroll",()=>{if(!this.isHeatmapFeatureEnabled())return;let i=window.scrollY||document.documentElement.scrollTop,n=document.documentElement.scrollHeight-window.innerHeight,a=n>0?i/n*100:0;a>t&&(t=a),r&&clearTimeout(r),r=setTimeout(()=>{this.heatmapQueue.push({project_id:this.config.apiKey,distinct_id:this.distinctId,session_id:this.sessionId,timestamp:new Date().toISOString(),page_url:window.location.href,interaction_type:"scroll",scroll_depth:t,viewport_width:window.innerWidth,viewport_height:window.innerHeight,page_width:document.documentElement.scrollWidth,page_height:document.documentElement.scrollHeight})},500)})}getBrowser(){if(typeof navigator>"u")return"unknown";let t=navigator.userAgent;return t.includes("Firefox")?"Firefox":t.includes("Edg")?"Edge":t.includes("Chrome")?"Chrome":t.includes("Safari")?"Safari":"Other"}};function ye(e){return new q(e)}var ke={Krypton:q,init:ye};typeof window<"u"&&(window.KryptonAnalytics=ke);var nt=ke;return Ie(at);})();
|
package/dist/index.d.mts
CHANGED
|
@@ -9,11 +9,21 @@ interface KryptonConfig {
|
|
|
9
9
|
heatmap?: boolean;
|
|
10
10
|
/** Require consent before tracking (default: false) */
|
|
11
11
|
consentRequired?: boolean;
|
|
12
|
+
/** Show a built-in consent popup (default: false) */
|
|
13
|
+
showConsentBanner?: boolean;
|
|
14
|
+
/** Optional initial consent values (default deny when consentRequired=true) */
|
|
15
|
+
consentCategories?: Partial<ConsentPreferences>;
|
|
12
16
|
/** Flush interval in milliseconds (default: 5000) */
|
|
13
17
|
flushInterval?: number;
|
|
14
18
|
/** Max events per batch (default: 20) */
|
|
15
19
|
batchSize?: number;
|
|
16
20
|
}
|
|
21
|
+
type ConsentCategory = "analytics" | "heatmaps" | "geo";
|
|
22
|
+
interface ConsentPreferences {
|
|
23
|
+
analytics: boolean;
|
|
24
|
+
heatmaps: boolean;
|
|
25
|
+
geo: boolean;
|
|
26
|
+
}
|
|
17
27
|
interface EventPayload {
|
|
18
28
|
project_id: string;
|
|
19
29
|
distinct_id: string;
|
|
@@ -61,18 +71,34 @@ declare class Krypton {
|
|
|
61
71
|
private eventQueue;
|
|
62
72
|
private heatmapQueue;
|
|
63
73
|
private flushTimer;
|
|
64
|
-
private consentGiven;
|
|
65
74
|
private initialized;
|
|
66
75
|
private lastSnapshotUrl;
|
|
76
|
+
private heatmapSetup;
|
|
77
|
+
private geoRequested;
|
|
78
|
+
private geoContext;
|
|
79
|
+
private consent;
|
|
67
80
|
private serverConfig;
|
|
68
81
|
private configFetched;
|
|
69
82
|
constructor(config: KryptonConfig);
|
|
70
83
|
private init;
|
|
84
|
+
private resolveInitialConsent;
|
|
85
|
+
private consentStorageKey;
|
|
86
|
+
private hasStoredConsent;
|
|
87
|
+
private loadStoredConsent;
|
|
88
|
+
private persistConsent;
|
|
89
|
+
private promotePersistentIds;
|
|
90
|
+
private canTrackAnalytics;
|
|
91
|
+
private isHeatmapFeatureEnabled;
|
|
71
92
|
private fetchConfig;
|
|
72
93
|
private setupTracking;
|
|
73
|
-
/**
|
|
94
|
+
/** Built-in consent popup with category toggles (analytics, heatmaps, geo). */
|
|
95
|
+
showConsentBanner(): void;
|
|
96
|
+
/** Set one or more consent categories and apply changes immediately. */
|
|
97
|
+
setConsent(next: Partial<ConsentPreferences>, persist?: boolean): void;
|
|
98
|
+
getConsent(): ConsentPreferences;
|
|
99
|
+
/** Backward-compatible: grant all categories. */
|
|
74
100
|
grantConsent(): void;
|
|
75
|
-
/**
|
|
101
|
+
/** Backward-compatible: revoke all categories and clear queues. */
|
|
76
102
|
revokeConsent(): void;
|
|
77
103
|
/** Identify a user with a custom distinct ID */
|
|
78
104
|
identify(distinctId: string): void;
|
|
@@ -80,10 +106,9 @@ declare class Krypton {
|
|
|
80
106
|
trackPageview(properties?: Record<string, unknown>): void;
|
|
81
107
|
/** Track a custom event */
|
|
82
108
|
track(eventName: string, properties?: Record<string, unknown>): void;
|
|
83
|
-
/** Flush all queued events to the server */
|
|
84
109
|
flush(): Promise<void>;
|
|
85
|
-
/** Shutdown the SDK */
|
|
86
110
|
shutdown(): void;
|
|
111
|
+
private captureGeoOnce;
|
|
87
112
|
private flushEvents;
|
|
88
113
|
private flushHeatmapEvents;
|
|
89
114
|
private captureSnapshot;
|
|
@@ -92,4 +117,4 @@ declare class Krypton {
|
|
|
92
117
|
}
|
|
93
118
|
declare function createKrypton(config: KryptonConfig): Krypton;
|
|
94
119
|
|
|
95
|
-
export { type EventPayload, type HeatmapEventPayload, Krypton, type KryptonConfig, createKrypton };
|
|
120
|
+
export { type ConsentCategory, type ConsentPreferences, type EventPayload, type HeatmapEventPayload, Krypton, type KryptonConfig, createKrypton };
|
package/dist/index.d.ts
CHANGED
|
@@ -9,11 +9,21 @@ interface KryptonConfig {
|
|
|
9
9
|
heatmap?: boolean;
|
|
10
10
|
/** Require consent before tracking (default: false) */
|
|
11
11
|
consentRequired?: boolean;
|
|
12
|
+
/** Show a built-in consent popup (default: false) */
|
|
13
|
+
showConsentBanner?: boolean;
|
|
14
|
+
/** Optional initial consent values (default deny when consentRequired=true) */
|
|
15
|
+
consentCategories?: Partial<ConsentPreferences>;
|
|
12
16
|
/** Flush interval in milliseconds (default: 5000) */
|
|
13
17
|
flushInterval?: number;
|
|
14
18
|
/** Max events per batch (default: 20) */
|
|
15
19
|
batchSize?: number;
|
|
16
20
|
}
|
|
21
|
+
type ConsentCategory = "analytics" | "heatmaps" | "geo";
|
|
22
|
+
interface ConsentPreferences {
|
|
23
|
+
analytics: boolean;
|
|
24
|
+
heatmaps: boolean;
|
|
25
|
+
geo: boolean;
|
|
26
|
+
}
|
|
17
27
|
interface EventPayload {
|
|
18
28
|
project_id: string;
|
|
19
29
|
distinct_id: string;
|
|
@@ -61,18 +71,34 @@ declare class Krypton {
|
|
|
61
71
|
private eventQueue;
|
|
62
72
|
private heatmapQueue;
|
|
63
73
|
private flushTimer;
|
|
64
|
-
private consentGiven;
|
|
65
74
|
private initialized;
|
|
66
75
|
private lastSnapshotUrl;
|
|
76
|
+
private heatmapSetup;
|
|
77
|
+
private geoRequested;
|
|
78
|
+
private geoContext;
|
|
79
|
+
private consent;
|
|
67
80
|
private serverConfig;
|
|
68
81
|
private configFetched;
|
|
69
82
|
constructor(config: KryptonConfig);
|
|
70
83
|
private init;
|
|
84
|
+
private resolveInitialConsent;
|
|
85
|
+
private consentStorageKey;
|
|
86
|
+
private hasStoredConsent;
|
|
87
|
+
private loadStoredConsent;
|
|
88
|
+
private persistConsent;
|
|
89
|
+
private promotePersistentIds;
|
|
90
|
+
private canTrackAnalytics;
|
|
91
|
+
private isHeatmapFeatureEnabled;
|
|
71
92
|
private fetchConfig;
|
|
72
93
|
private setupTracking;
|
|
73
|
-
/**
|
|
94
|
+
/** Built-in consent popup with category toggles (analytics, heatmaps, geo). */
|
|
95
|
+
showConsentBanner(): void;
|
|
96
|
+
/** Set one or more consent categories and apply changes immediately. */
|
|
97
|
+
setConsent(next: Partial<ConsentPreferences>, persist?: boolean): void;
|
|
98
|
+
getConsent(): ConsentPreferences;
|
|
99
|
+
/** Backward-compatible: grant all categories. */
|
|
74
100
|
grantConsent(): void;
|
|
75
|
-
/**
|
|
101
|
+
/** Backward-compatible: revoke all categories and clear queues. */
|
|
76
102
|
revokeConsent(): void;
|
|
77
103
|
/** Identify a user with a custom distinct ID */
|
|
78
104
|
identify(distinctId: string): void;
|
|
@@ -80,10 +106,9 @@ declare class Krypton {
|
|
|
80
106
|
trackPageview(properties?: Record<string, unknown>): void;
|
|
81
107
|
/** Track a custom event */
|
|
82
108
|
track(eventName: string, properties?: Record<string, unknown>): void;
|
|
83
|
-
/** Flush all queued events to the server */
|
|
84
109
|
flush(): Promise<void>;
|
|
85
|
-
/** Shutdown the SDK */
|
|
86
110
|
shutdown(): void;
|
|
111
|
+
private captureGeoOnce;
|
|
87
112
|
private flushEvents;
|
|
88
113
|
private flushHeatmapEvents;
|
|
89
114
|
private captureSnapshot;
|
|
@@ -92,4 +117,4 @@ declare class Krypton {
|
|
|
92
117
|
}
|
|
93
118
|
declare function createKrypton(config: KryptonConfig): Krypton;
|
|
94
119
|
|
|
95
|
-
export { type EventPayload, type HeatmapEventPayload, Krypton, type KryptonConfig, createKrypton };
|
|
120
|
+
export { type ConsentCategory, type ConsentPreferences, type EventPayload, type HeatmapEventPayload, Krypton, type KryptonConfig, createKrypton };
|
package/dist/index.js
CHANGED
|
@@ -104,30 +104,91 @@ var Krypton = class {
|
|
|
104
104
|
this.eventQueue = [];
|
|
105
105
|
this.heatmapQueue = [];
|
|
106
106
|
this.flushTimer = null;
|
|
107
|
-
this.consentGiven = false;
|
|
108
107
|
this.initialized = false;
|
|
109
108
|
this.lastSnapshotUrl = null;
|
|
109
|
+
this.heatmapSetup = false;
|
|
110
|
+
this.geoRequested = false;
|
|
111
|
+
this.geoContext = null;
|
|
110
112
|
this.serverConfig = null;
|
|
111
113
|
this.configFetched = false;
|
|
112
114
|
this.config = {
|
|
113
115
|
autoPageview: true,
|
|
114
116
|
heatmap: false,
|
|
115
117
|
consentRequired: false,
|
|
118
|
+
showConsentBanner: false,
|
|
119
|
+
consentCategories: {},
|
|
116
120
|
flushInterval: 5e3,
|
|
117
121
|
batchSize: 20,
|
|
118
122
|
...config
|
|
119
123
|
};
|
|
120
|
-
this.distinctId =
|
|
121
|
-
this.sessionId =
|
|
122
|
-
|
|
123
|
-
|
|
124
|
+
this.distinctId = generateId();
|
|
125
|
+
this.sessionId = generateId();
|
|
126
|
+
this.consent = this.resolveInitialConsent();
|
|
127
|
+
if (this.canTrackAnalytics()) {
|
|
128
|
+
this.promotePersistentIds();
|
|
124
129
|
}
|
|
125
130
|
this.init();
|
|
126
131
|
}
|
|
127
132
|
init() {
|
|
128
133
|
if (this.initialized) return;
|
|
129
134
|
this.initialized = true;
|
|
130
|
-
this.fetchConfig().then(() =>
|
|
135
|
+
this.fetchConfig().then(() => {
|
|
136
|
+
this.setupTracking();
|
|
137
|
+
if (this.config.consentRequired && this.config.showConsentBanner && !this.hasStoredConsent()) {
|
|
138
|
+
this.showConsentBanner();
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
resolveInitialConsent() {
|
|
143
|
+
const stored = this.loadStoredConsent();
|
|
144
|
+
if (stored) return stored;
|
|
145
|
+
const base = this.config.consentRequired ? { analytics: false, heatmaps: false, geo: false } : {
|
|
146
|
+
analytics: true,
|
|
147
|
+
heatmaps: !!this.config.heatmap,
|
|
148
|
+
geo: false
|
|
149
|
+
};
|
|
150
|
+
return {
|
|
151
|
+
...base,
|
|
152
|
+
...this.config.consentCategories
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
consentStorageKey() {
|
|
156
|
+
return `_krypton_consent_${this.config.apiKey}`;
|
|
157
|
+
}
|
|
158
|
+
hasStoredConsent() {
|
|
159
|
+
if (typeof localStorage === "undefined") return false;
|
|
160
|
+
return !!localStorage.getItem(this.consentStorageKey());
|
|
161
|
+
}
|
|
162
|
+
loadStoredConsent() {
|
|
163
|
+
if (typeof localStorage === "undefined") return null;
|
|
164
|
+
const raw = localStorage.getItem(this.consentStorageKey());
|
|
165
|
+
if (!raw) return null;
|
|
166
|
+
try {
|
|
167
|
+
const parsed = JSON.parse(raw);
|
|
168
|
+
return {
|
|
169
|
+
analytics: !!parsed.analytics,
|
|
170
|
+
heatmaps: !!parsed.heatmaps,
|
|
171
|
+
geo: !!parsed.geo
|
|
172
|
+
};
|
|
173
|
+
} catch {
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
persistConsent() {
|
|
178
|
+
if (typeof localStorage === "undefined") return;
|
|
179
|
+
localStorage.setItem(this.consentStorageKey(), JSON.stringify(this.consent));
|
|
180
|
+
}
|
|
181
|
+
promotePersistentIds() {
|
|
182
|
+
this.distinctId = getDistinctId();
|
|
183
|
+
this.sessionId = getSessionId();
|
|
184
|
+
}
|
|
185
|
+
canTrackAnalytics() {
|
|
186
|
+
return !!this.consent.analytics;
|
|
187
|
+
}
|
|
188
|
+
isHeatmapFeatureEnabled() {
|
|
189
|
+
if (!this.config.heatmap) return false;
|
|
190
|
+
if (this.configFetched && !this.serverConfig?.heatmaps_enabled) return false;
|
|
191
|
+
return !!this.consent.heatmaps;
|
|
131
192
|
}
|
|
132
193
|
async fetchConfig() {
|
|
133
194
|
if (typeof window === "undefined") return;
|
|
@@ -159,76 +220,188 @@ var Krypton = class {
|
|
|
159
220
|
}
|
|
160
221
|
setupTracking() {
|
|
161
222
|
this.flushTimer = setInterval(() => this.flush(), this.config.flushInterval);
|
|
162
|
-
if (typeof window
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
223
|
+
if (typeof window === "undefined") return;
|
|
224
|
+
window.addEventListener("beforeunload", () => this.flush());
|
|
225
|
+
if (this.config.autoPageview && this.canTrackAnalytics()) {
|
|
226
|
+
this.trackPageview();
|
|
227
|
+
}
|
|
228
|
+
const originalPushState = history.pushState;
|
|
229
|
+
history.pushState = (...args) => {
|
|
230
|
+
originalPushState.apply(history, args);
|
|
231
|
+
if (this.config.autoPageview && this.canTrackAnalytics()) {
|
|
232
|
+
setTimeout(() => this.trackPageview(), 0);
|
|
166
233
|
}
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
}
|
|
185
|
-
});
|
|
186
|
-
if (heatmapEnabled && this.consentGiven) {
|
|
187
|
-
this.setupHeatmap();
|
|
234
|
+
if (this.isHeatmapFeatureEnabled()) {
|
|
235
|
+
setTimeout(() => this.captureSnapshot(), 0);
|
|
236
|
+
}
|
|
237
|
+
};
|
|
238
|
+
const originalReplaceState = history.replaceState;
|
|
239
|
+
history.replaceState = (...args) => {
|
|
240
|
+
originalReplaceState.apply(history, args);
|
|
241
|
+
if (this.config.autoPageview && this.canTrackAnalytics()) {
|
|
242
|
+
setTimeout(() => this.trackPageview(), 0);
|
|
243
|
+
}
|
|
244
|
+
if (this.isHeatmapFeatureEnabled()) {
|
|
245
|
+
setTimeout(() => this.captureSnapshot(), 0);
|
|
246
|
+
}
|
|
247
|
+
};
|
|
248
|
+
window.addEventListener("popstate", () => {
|
|
249
|
+
if (this.config.autoPageview && this.canTrackAnalytics()) {
|
|
250
|
+
setTimeout(() => this.trackPageview(), 0);
|
|
188
251
|
}
|
|
252
|
+
if (this.isHeatmapFeatureEnabled()) {
|
|
253
|
+
setTimeout(() => this.captureSnapshot(), 0);
|
|
254
|
+
}
|
|
255
|
+
});
|
|
256
|
+
if (this.isHeatmapFeatureEnabled()) {
|
|
257
|
+
this.setupHeatmap();
|
|
258
|
+
}
|
|
259
|
+
if (this.consent.geo) {
|
|
260
|
+
this.captureGeoOnce();
|
|
189
261
|
}
|
|
190
262
|
}
|
|
191
|
-
/**
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
if (
|
|
195
|
-
|
|
263
|
+
/** Built-in consent popup with category toggles (analytics, heatmaps, geo). */
|
|
264
|
+
showConsentBanner() {
|
|
265
|
+
if (typeof document === "undefined") return;
|
|
266
|
+
if (document.getElementById("krypton-consent-banner")) return;
|
|
267
|
+
const banner = document.createElement("div");
|
|
268
|
+
banner.id = "krypton-consent-banner";
|
|
269
|
+
banner.style.cssText = [
|
|
270
|
+
"position:fixed",
|
|
271
|
+
"left:16px",
|
|
272
|
+
"right:16px",
|
|
273
|
+
"bottom:16px",
|
|
274
|
+
"z-index:2147483647",
|
|
275
|
+
"max-width:720px",
|
|
276
|
+
"margin:0 auto",
|
|
277
|
+
"background:#111827",
|
|
278
|
+
"color:#f9fafb",
|
|
279
|
+
"border-radius:12px",
|
|
280
|
+
"padding:16px",
|
|
281
|
+
"box-shadow:0 12px 30px rgba(0,0,0,0.35)",
|
|
282
|
+
"font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif",
|
|
283
|
+
"font-size:14px",
|
|
284
|
+
"line-height:1.4"
|
|
285
|
+
].join(";");
|
|
286
|
+
const checked = (value) => value ? "checked" : "";
|
|
287
|
+
banner.innerHTML = `
|
|
288
|
+
<div style="font-weight:600;margin-bottom:6px">Privacy preferences</div>
|
|
289
|
+
<div style="opacity:0.9;margin-bottom:10px">Choose what data you allow us to collect.</div>
|
|
290
|
+
<label style="display:flex;gap:8px;align-items:flex-start;margin:6px 0">
|
|
291
|
+
<input type="checkbox" id="krypton-consent-analytics" ${checked(this.consent.analytics)} />
|
|
292
|
+
<span><strong>Analytics</strong> (pageviews and custom events)</span>
|
|
293
|
+
</label>
|
|
294
|
+
<label style="display:flex;gap:8px;align-items:flex-start;margin:6px 0">
|
|
295
|
+
<input type="checkbox" id="krypton-consent-heatmaps" ${checked(this.consent.heatmaps)} />
|
|
296
|
+
<span><strong>Heatmaps</strong> (click and scroll interaction maps)</span>
|
|
297
|
+
</label>
|
|
298
|
+
<label style="display:flex;gap:8px;align-items:flex-start;margin:6px 0 12px 0">
|
|
299
|
+
<input type="checkbox" id="krypton-consent-geo" ${checked(this.consent.geo)} />
|
|
300
|
+
<span><strong>Geo location</strong> (browser geolocation if available)</span>
|
|
301
|
+
</label>
|
|
302
|
+
<div style="display:flex;gap:8px;flex-wrap:wrap">
|
|
303
|
+
<button id="krypton-consent-save" style="border:0;background:#2563eb;color:#fff;padding:8px 12px;border-radius:8px;cursor:pointer">Accept selected</button>
|
|
304
|
+
<button id="krypton-consent-all" style="border:0;background:#16a34a;color:#fff;padding:8px 12px;border-radius:8px;cursor:pointer">Accept all</button>
|
|
305
|
+
<button id="krypton-consent-none" style="border:1px solid #4b5563;background:transparent;color:#f9fafb;padding:8px 12px;border-radius:8px;cursor:pointer">Reject all</button>
|
|
306
|
+
</div>
|
|
307
|
+
`;
|
|
308
|
+
const remove = () => {
|
|
309
|
+
banner.remove();
|
|
310
|
+
};
|
|
311
|
+
const readValue = (id) => {
|
|
312
|
+
const el = document.getElementById(id);
|
|
313
|
+
return !!el?.checked;
|
|
314
|
+
};
|
|
315
|
+
banner.querySelector("#krypton-consent-save")?.addEventListener("click", () => {
|
|
316
|
+
this.setConsent({
|
|
317
|
+
analytics: readValue("krypton-consent-analytics"),
|
|
318
|
+
heatmaps: readValue("krypton-consent-heatmaps"),
|
|
319
|
+
geo: readValue("krypton-consent-geo")
|
|
320
|
+
});
|
|
321
|
+
remove();
|
|
322
|
+
});
|
|
323
|
+
banner.querySelector("#krypton-consent-all")?.addEventListener("click", () => {
|
|
324
|
+
this.setConsent({ analytics: true, heatmaps: true, geo: true });
|
|
325
|
+
remove();
|
|
326
|
+
});
|
|
327
|
+
banner.querySelector("#krypton-consent-none")?.addEventListener("click", () => {
|
|
328
|
+
this.setConsent({ analytics: false, heatmaps: false, geo: false });
|
|
329
|
+
remove();
|
|
330
|
+
});
|
|
331
|
+
document.body.appendChild(banner);
|
|
332
|
+
}
|
|
333
|
+
/** Set one or more consent categories and apply changes immediately. */
|
|
334
|
+
setConsent(next, persist = true) {
|
|
335
|
+
const prev = { ...this.consent };
|
|
336
|
+
this.consent = {
|
|
337
|
+
analytics: next.analytics ?? prev.analytics,
|
|
338
|
+
heatmaps: next.heatmaps ?? prev.heatmaps,
|
|
339
|
+
geo: next.geo ?? prev.geo
|
|
340
|
+
};
|
|
341
|
+
if (persist) {
|
|
342
|
+
this.persistConsent();
|
|
343
|
+
}
|
|
344
|
+
if (!prev.analytics && this.consent.analytics) {
|
|
345
|
+
this.promotePersistentIds();
|
|
346
|
+
if (this.config.autoPageview) {
|
|
347
|
+
this.trackPageview();
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
if (prev.analytics && !this.consent.analytics) {
|
|
351
|
+
this.eventQueue = [];
|
|
196
352
|
}
|
|
197
|
-
|
|
198
|
-
if (heatmapEnabled) {
|
|
353
|
+
if (!prev.heatmaps && this.isHeatmapFeatureEnabled()) {
|
|
199
354
|
this.setupHeatmap();
|
|
355
|
+
this.captureSnapshot();
|
|
356
|
+
}
|
|
357
|
+
if (prev.heatmaps && !this.consent.heatmaps) {
|
|
358
|
+
this.heatmapQueue = [];
|
|
359
|
+
}
|
|
360
|
+
if (!prev.geo && this.consent.geo) {
|
|
361
|
+
this.captureGeoOnce();
|
|
200
362
|
}
|
|
201
363
|
}
|
|
202
|
-
|
|
364
|
+
getConsent() {
|
|
365
|
+
return { ...this.consent };
|
|
366
|
+
}
|
|
367
|
+
/** Backward-compatible: grant all categories. */
|
|
368
|
+
grantConsent() {
|
|
369
|
+
this.setConsent({ analytics: true, heatmaps: true, geo: true });
|
|
370
|
+
}
|
|
371
|
+
/** Backward-compatible: revoke all categories and clear queues. */
|
|
203
372
|
revokeConsent() {
|
|
204
|
-
this.
|
|
373
|
+
this.setConsent({ analytics: false, heatmaps: false, geo: false });
|
|
205
374
|
this.eventQueue = [];
|
|
206
375
|
this.heatmapQueue = [];
|
|
207
376
|
}
|
|
208
377
|
/** Identify a user with a custom distinct ID */
|
|
209
378
|
identify(distinctId) {
|
|
210
379
|
this.distinctId = distinctId;
|
|
211
|
-
if (typeof localStorage !== "undefined") {
|
|
380
|
+
if (typeof localStorage !== "undefined" && this.canTrackAnalytics()) {
|
|
212
381
|
localStorage.setItem("_krypton_did", distinctId);
|
|
213
382
|
}
|
|
214
383
|
}
|
|
215
384
|
/** Track a pageview */
|
|
216
385
|
trackPageview(properties) {
|
|
217
|
-
if (!this.
|
|
386
|
+
if (!this.canTrackAnalytics()) return;
|
|
218
387
|
this.track("$pageview", {
|
|
219
388
|
...properties
|
|
220
389
|
});
|
|
221
390
|
}
|
|
222
391
|
/** Track a custom event */
|
|
223
392
|
track(eventName, properties) {
|
|
224
|
-
if (!this.
|
|
393
|
+
if (!this.canTrackAnalytics()) return;
|
|
225
394
|
const utm = getUTMParams();
|
|
395
|
+
const mergedProperties = { ...properties || {} };
|
|
396
|
+
if (this.consent.geo && this.geoContext) {
|
|
397
|
+
mergedProperties.geo = this.geoContext;
|
|
398
|
+
}
|
|
226
399
|
const event = {
|
|
227
400
|
project_id: this.config.apiKey,
|
|
228
401
|
distinct_id: this.distinctId,
|
|
229
402
|
event_name: eventName,
|
|
230
403
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
231
|
-
properties,
|
|
404
|
+
properties: mergedProperties,
|
|
232
405
|
page_url: typeof window !== "undefined" ? window.location.href : "",
|
|
233
406
|
page_title: typeof document !== "undefined" ? document.title : "",
|
|
234
407
|
referrer: typeof document !== "undefined" ? document.referrer : "",
|
|
@@ -248,11 +421,9 @@ var Krypton = class {
|
|
|
248
421
|
this.flush();
|
|
249
422
|
}
|
|
250
423
|
}
|
|
251
|
-
/** Flush all queued events to the server */
|
|
252
424
|
async flush() {
|
|
253
425
|
await Promise.all([this.flushEvents(), this.flushHeatmapEvents()]);
|
|
254
426
|
}
|
|
255
|
-
/** Shutdown the SDK */
|
|
256
427
|
shutdown() {
|
|
257
428
|
if (this.flushTimer) {
|
|
258
429
|
clearInterval(this.flushTimer);
|
|
@@ -260,7 +431,30 @@ var Krypton = class {
|
|
|
260
431
|
}
|
|
261
432
|
this.flush();
|
|
262
433
|
}
|
|
263
|
-
|
|
434
|
+
captureGeoOnce() {
|
|
435
|
+
if (this.geoRequested) return;
|
|
436
|
+
if (!this.consent.geo) return;
|
|
437
|
+
if (typeof navigator === "undefined" || !navigator.geolocation) return;
|
|
438
|
+
this.geoRequested = true;
|
|
439
|
+
navigator.geolocation.getCurrentPosition(
|
|
440
|
+
(pos) => {
|
|
441
|
+
const round = (value, precision = 3) => Number(value.toFixed(precision));
|
|
442
|
+
this.geoContext = {
|
|
443
|
+
lat: round(pos.coords.latitude),
|
|
444
|
+
lon: round(pos.coords.longitude),
|
|
445
|
+
accuracy_m: Math.round(pos.coords.accuracy),
|
|
446
|
+
captured_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
447
|
+
};
|
|
448
|
+
},
|
|
449
|
+
() => {
|
|
450
|
+
},
|
|
451
|
+
{
|
|
452
|
+
enableHighAccuracy: false,
|
|
453
|
+
maximumAge: 10 * 60 * 1e3,
|
|
454
|
+
timeout: 5e3
|
|
455
|
+
}
|
|
456
|
+
);
|
|
457
|
+
}
|
|
264
458
|
async flushEvents() {
|
|
265
459
|
if (this.eventQueue.length === 0) return;
|
|
266
460
|
const events = this.eventQueue.splice(0, this.eventQueue.length);
|
|
@@ -303,6 +497,7 @@ var Krypton = class {
|
|
|
303
497
|
}
|
|
304
498
|
captureSnapshot() {
|
|
305
499
|
if (typeof window === "undefined" || typeof document === "undefined") return;
|
|
500
|
+
if (!this.isHeatmapFeatureEnabled()) return;
|
|
306
501
|
const currentUrl = window.location.href;
|
|
307
502
|
if (this.lastSnapshotUrl === currentUrl) return;
|
|
308
503
|
this.lastSnapshotUrl = currentUrl;
|
|
@@ -338,9 +533,11 @@ var Krypton = class {
|
|
|
338
533
|
}
|
|
339
534
|
setupHeatmap() {
|
|
340
535
|
if (typeof window === "undefined") return;
|
|
536
|
+
if (this.heatmapSetup) return;
|
|
537
|
+
this.heatmapSetup = true;
|
|
341
538
|
this.captureSnapshot();
|
|
342
539
|
document.addEventListener("click", (e) => {
|
|
343
|
-
if (!this.
|
|
540
|
+
if (!this.isHeatmapFeatureEnabled()) return;
|
|
344
541
|
const target = e.target;
|
|
345
542
|
this.heatmapQueue.push({
|
|
346
543
|
project_id: this.config.apiKey,
|
|
@@ -361,7 +558,7 @@ var Krypton = class {
|
|
|
361
558
|
let maxScrollDepth = 0;
|
|
362
559
|
let scrollTimeout = null;
|
|
363
560
|
window.addEventListener("scroll", () => {
|
|
364
|
-
if (!this.
|
|
561
|
+
if (!this.isHeatmapFeatureEnabled()) return;
|
|
365
562
|
const scrollTop = window.scrollY || document.documentElement.scrollTop;
|
|
366
563
|
const docHeight = document.documentElement.scrollHeight - window.innerHeight;
|
|
367
564
|
const depth = docHeight > 0 ? scrollTop / docHeight * 100 : 0;
|
package/dist/index.mjs
CHANGED
|
@@ -79,30 +79,91 @@ var Krypton = class {
|
|
|
79
79
|
this.eventQueue = [];
|
|
80
80
|
this.heatmapQueue = [];
|
|
81
81
|
this.flushTimer = null;
|
|
82
|
-
this.consentGiven = false;
|
|
83
82
|
this.initialized = false;
|
|
84
83
|
this.lastSnapshotUrl = null;
|
|
84
|
+
this.heatmapSetup = false;
|
|
85
|
+
this.geoRequested = false;
|
|
86
|
+
this.geoContext = null;
|
|
85
87
|
this.serverConfig = null;
|
|
86
88
|
this.configFetched = false;
|
|
87
89
|
this.config = {
|
|
88
90
|
autoPageview: true,
|
|
89
91
|
heatmap: false,
|
|
90
92
|
consentRequired: false,
|
|
93
|
+
showConsentBanner: false,
|
|
94
|
+
consentCategories: {},
|
|
91
95
|
flushInterval: 5e3,
|
|
92
96
|
batchSize: 20,
|
|
93
97
|
...config
|
|
94
98
|
};
|
|
95
|
-
this.distinctId =
|
|
96
|
-
this.sessionId =
|
|
97
|
-
|
|
98
|
-
|
|
99
|
+
this.distinctId = generateId();
|
|
100
|
+
this.sessionId = generateId();
|
|
101
|
+
this.consent = this.resolveInitialConsent();
|
|
102
|
+
if (this.canTrackAnalytics()) {
|
|
103
|
+
this.promotePersistentIds();
|
|
99
104
|
}
|
|
100
105
|
this.init();
|
|
101
106
|
}
|
|
102
107
|
init() {
|
|
103
108
|
if (this.initialized) return;
|
|
104
109
|
this.initialized = true;
|
|
105
|
-
this.fetchConfig().then(() =>
|
|
110
|
+
this.fetchConfig().then(() => {
|
|
111
|
+
this.setupTracking();
|
|
112
|
+
if (this.config.consentRequired && this.config.showConsentBanner && !this.hasStoredConsent()) {
|
|
113
|
+
this.showConsentBanner();
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
resolveInitialConsent() {
|
|
118
|
+
const stored = this.loadStoredConsent();
|
|
119
|
+
if (stored) return stored;
|
|
120
|
+
const base = this.config.consentRequired ? { analytics: false, heatmaps: false, geo: false } : {
|
|
121
|
+
analytics: true,
|
|
122
|
+
heatmaps: !!this.config.heatmap,
|
|
123
|
+
geo: false
|
|
124
|
+
};
|
|
125
|
+
return {
|
|
126
|
+
...base,
|
|
127
|
+
...this.config.consentCategories
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
consentStorageKey() {
|
|
131
|
+
return `_krypton_consent_${this.config.apiKey}`;
|
|
132
|
+
}
|
|
133
|
+
hasStoredConsent() {
|
|
134
|
+
if (typeof localStorage === "undefined") return false;
|
|
135
|
+
return !!localStorage.getItem(this.consentStorageKey());
|
|
136
|
+
}
|
|
137
|
+
loadStoredConsent() {
|
|
138
|
+
if (typeof localStorage === "undefined") return null;
|
|
139
|
+
const raw = localStorage.getItem(this.consentStorageKey());
|
|
140
|
+
if (!raw) return null;
|
|
141
|
+
try {
|
|
142
|
+
const parsed = JSON.parse(raw);
|
|
143
|
+
return {
|
|
144
|
+
analytics: !!parsed.analytics,
|
|
145
|
+
heatmaps: !!parsed.heatmaps,
|
|
146
|
+
geo: !!parsed.geo
|
|
147
|
+
};
|
|
148
|
+
} catch {
|
|
149
|
+
return null;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
persistConsent() {
|
|
153
|
+
if (typeof localStorage === "undefined") return;
|
|
154
|
+
localStorage.setItem(this.consentStorageKey(), JSON.stringify(this.consent));
|
|
155
|
+
}
|
|
156
|
+
promotePersistentIds() {
|
|
157
|
+
this.distinctId = getDistinctId();
|
|
158
|
+
this.sessionId = getSessionId();
|
|
159
|
+
}
|
|
160
|
+
canTrackAnalytics() {
|
|
161
|
+
return !!this.consent.analytics;
|
|
162
|
+
}
|
|
163
|
+
isHeatmapFeatureEnabled() {
|
|
164
|
+
if (!this.config.heatmap) return false;
|
|
165
|
+
if (this.configFetched && !this.serverConfig?.heatmaps_enabled) return false;
|
|
166
|
+
return !!this.consent.heatmaps;
|
|
106
167
|
}
|
|
107
168
|
async fetchConfig() {
|
|
108
169
|
if (typeof window === "undefined") return;
|
|
@@ -134,76 +195,188 @@ var Krypton = class {
|
|
|
134
195
|
}
|
|
135
196
|
setupTracking() {
|
|
136
197
|
this.flushTimer = setInterval(() => this.flush(), this.config.flushInterval);
|
|
137
|
-
if (typeof window
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
198
|
+
if (typeof window === "undefined") return;
|
|
199
|
+
window.addEventListener("beforeunload", () => this.flush());
|
|
200
|
+
if (this.config.autoPageview && this.canTrackAnalytics()) {
|
|
201
|
+
this.trackPageview();
|
|
202
|
+
}
|
|
203
|
+
const originalPushState = history.pushState;
|
|
204
|
+
history.pushState = (...args) => {
|
|
205
|
+
originalPushState.apply(history, args);
|
|
206
|
+
if (this.config.autoPageview && this.canTrackAnalytics()) {
|
|
207
|
+
setTimeout(() => this.trackPageview(), 0);
|
|
141
208
|
}
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
}
|
|
160
|
-
});
|
|
161
|
-
if (heatmapEnabled && this.consentGiven) {
|
|
162
|
-
this.setupHeatmap();
|
|
209
|
+
if (this.isHeatmapFeatureEnabled()) {
|
|
210
|
+
setTimeout(() => this.captureSnapshot(), 0);
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
const originalReplaceState = history.replaceState;
|
|
214
|
+
history.replaceState = (...args) => {
|
|
215
|
+
originalReplaceState.apply(history, args);
|
|
216
|
+
if (this.config.autoPageview && this.canTrackAnalytics()) {
|
|
217
|
+
setTimeout(() => this.trackPageview(), 0);
|
|
218
|
+
}
|
|
219
|
+
if (this.isHeatmapFeatureEnabled()) {
|
|
220
|
+
setTimeout(() => this.captureSnapshot(), 0);
|
|
221
|
+
}
|
|
222
|
+
};
|
|
223
|
+
window.addEventListener("popstate", () => {
|
|
224
|
+
if (this.config.autoPageview && this.canTrackAnalytics()) {
|
|
225
|
+
setTimeout(() => this.trackPageview(), 0);
|
|
163
226
|
}
|
|
227
|
+
if (this.isHeatmapFeatureEnabled()) {
|
|
228
|
+
setTimeout(() => this.captureSnapshot(), 0);
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
if (this.isHeatmapFeatureEnabled()) {
|
|
232
|
+
this.setupHeatmap();
|
|
233
|
+
}
|
|
234
|
+
if (this.consent.geo) {
|
|
235
|
+
this.captureGeoOnce();
|
|
164
236
|
}
|
|
165
237
|
}
|
|
166
|
-
/**
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
if (
|
|
170
|
-
|
|
238
|
+
/** Built-in consent popup with category toggles (analytics, heatmaps, geo). */
|
|
239
|
+
showConsentBanner() {
|
|
240
|
+
if (typeof document === "undefined") return;
|
|
241
|
+
if (document.getElementById("krypton-consent-banner")) return;
|
|
242
|
+
const banner = document.createElement("div");
|
|
243
|
+
banner.id = "krypton-consent-banner";
|
|
244
|
+
banner.style.cssText = [
|
|
245
|
+
"position:fixed",
|
|
246
|
+
"left:16px",
|
|
247
|
+
"right:16px",
|
|
248
|
+
"bottom:16px",
|
|
249
|
+
"z-index:2147483647",
|
|
250
|
+
"max-width:720px",
|
|
251
|
+
"margin:0 auto",
|
|
252
|
+
"background:#111827",
|
|
253
|
+
"color:#f9fafb",
|
|
254
|
+
"border-radius:12px",
|
|
255
|
+
"padding:16px",
|
|
256
|
+
"box-shadow:0 12px 30px rgba(0,0,0,0.35)",
|
|
257
|
+
"font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif",
|
|
258
|
+
"font-size:14px",
|
|
259
|
+
"line-height:1.4"
|
|
260
|
+
].join(";");
|
|
261
|
+
const checked = (value) => value ? "checked" : "";
|
|
262
|
+
banner.innerHTML = `
|
|
263
|
+
<div style="font-weight:600;margin-bottom:6px">Privacy preferences</div>
|
|
264
|
+
<div style="opacity:0.9;margin-bottom:10px">Choose what data you allow us to collect.</div>
|
|
265
|
+
<label style="display:flex;gap:8px;align-items:flex-start;margin:6px 0">
|
|
266
|
+
<input type="checkbox" id="krypton-consent-analytics" ${checked(this.consent.analytics)} />
|
|
267
|
+
<span><strong>Analytics</strong> (pageviews and custom events)</span>
|
|
268
|
+
</label>
|
|
269
|
+
<label style="display:flex;gap:8px;align-items:flex-start;margin:6px 0">
|
|
270
|
+
<input type="checkbox" id="krypton-consent-heatmaps" ${checked(this.consent.heatmaps)} />
|
|
271
|
+
<span><strong>Heatmaps</strong> (click and scroll interaction maps)</span>
|
|
272
|
+
</label>
|
|
273
|
+
<label style="display:flex;gap:8px;align-items:flex-start;margin:6px 0 12px 0">
|
|
274
|
+
<input type="checkbox" id="krypton-consent-geo" ${checked(this.consent.geo)} />
|
|
275
|
+
<span><strong>Geo location</strong> (browser geolocation if available)</span>
|
|
276
|
+
</label>
|
|
277
|
+
<div style="display:flex;gap:8px;flex-wrap:wrap">
|
|
278
|
+
<button id="krypton-consent-save" style="border:0;background:#2563eb;color:#fff;padding:8px 12px;border-radius:8px;cursor:pointer">Accept selected</button>
|
|
279
|
+
<button id="krypton-consent-all" style="border:0;background:#16a34a;color:#fff;padding:8px 12px;border-radius:8px;cursor:pointer">Accept all</button>
|
|
280
|
+
<button id="krypton-consent-none" style="border:1px solid #4b5563;background:transparent;color:#f9fafb;padding:8px 12px;border-radius:8px;cursor:pointer">Reject all</button>
|
|
281
|
+
</div>
|
|
282
|
+
`;
|
|
283
|
+
const remove = () => {
|
|
284
|
+
banner.remove();
|
|
285
|
+
};
|
|
286
|
+
const readValue = (id) => {
|
|
287
|
+
const el = document.getElementById(id);
|
|
288
|
+
return !!el?.checked;
|
|
289
|
+
};
|
|
290
|
+
banner.querySelector("#krypton-consent-save")?.addEventListener("click", () => {
|
|
291
|
+
this.setConsent({
|
|
292
|
+
analytics: readValue("krypton-consent-analytics"),
|
|
293
|
+
heatmaps: readValue("krypton-consent-heatmaps"),
|
|
294
|
+
geo: readValue("krypton-consent-geo")
|
|
295
|
+
});
|
|
296
|
+
remove();
|
|
297
|
+
});
|
|
298
|
+
banner.querySelector("#krypton-consent-all")?.addEventListener("click", () => {
|
|
299
|
+
this.setConsent({ analytics: true, heatmaps: true, geo: true });
|
|
300
|
+
remove();
|
|
301
|
+
});
|
|
302
|
+
banner.querySelector("#krypton-consent-none")?.addEventListener("click", () => {
|
|
303
|
+
this.setConsent({ analytics: false, heatmaps: false, geo: false });
|
|
304
|
+
remove();
|
|
305
|
+
});
|
|
306
|
+
document.body.appendChild(banner);
|
|
307
|
+
}
|
|
308
|
+
/** Set one or more consent categories and apply changes immediately. */
|
|
309
|
+
setConsent(next, persist = true) {
|
|
310
|
+
const prev = { ...this.consent };
|
|
311
|
+
this.consent = {
|
|
312
|
+
analytics: next.analytics ?? prev.analytics,
|
|
313
|
+
heatmaps: next.heatmaps ?? prev.heatmaps,
|
|
314
|
+
geo: next.geo ?? prev.geo
|
|
315
|
+
};
|
|
316
|
+
if (persist) {
|
|
317
|
+
this.persistConsent();
|
|
318
|
+
}
|
|
319
|
+
if (!prev.analytics && this.consent.analytics) {
|
|
320
|
+
this.promotePersistentIds();
|
|
321
|
+
if (this.config.autoPageview) {
|
|
322
|
+
this.trackPageview();
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
if (prev.analytics && !this.consent.analytics) {
|
|
326
|
+
this.eventQueue = [];
|
|
171
327
|
}
|
|
172
|
-
|
|
173
|
-
if (heatmapEnabled) {
|
|
328
|
+
if (!prev.heatmaps && this.isHeatmapFeatureEnabled()) {
|
|
174
329
|
this.setupHeatmap();
|
|
330
|
+
this.captureSnapshot();
|
|
331
|
+
}
|
|
332
|
+
if (prev.heatmaps && !this.consent.heatmaps) {
|
|
333
|
+
this.heatmapQueue = [];
|
|
334
|
+
}
|
|
335
|
+
if (!prev.geo && this.consent.geo) {
|
|
336
|
+
this.captureGeoOnce();
|
|
175
337
|
}
|
|
176
338
|
}
|
|
177
|
-
|
|
339
|
+
getConsent() {
|
|
340
|
+
return { ...this.consent };
|
|
341
|
+
}
|
|
342
|
+
/** Backward-compatible: grant all categories. */
|
|
343
|
+
grantConsent() {
|
|
344
|
+
this.setConsent({ analytics: true, heatmaps: true, geo: true });
|
|
345
|
+
}
|
|
346
|
+
/** Backward-compatible: revoke all categories and clear queues. */
|
|
178
347
|
revokeConsent() {
|
|
179
|
-
this.
|
|
348
|
+
this.setConsent({ analytics: false, heatmaps: false, geo: false });
|
|
180
349
|
this.eventQueue = [];
|
|
181
350
|
this.heatmapQueue = [];
|
|
182
351
|
}
|
|
183
352
|
/** Identify a user with a custom distinct ID */
|
|
184
353
|
identify(distinctId) {
|
|
185
354
|
this.distinctId = distinctId;
|
|
186
|
-
if (typeof localStorage !== "undefined") {
|
|
355
|
+
if (typeof localStorage !== "undefined" && this.canTrackAnalytics()) {
|
|
187
356
|
localStorage.setItem("_krypton_did", distinctId);
|
|
188
357
|
}
|
|
189
358
|
}
|
|
190
359
|
/** Track a pageview */
|
|
191
360
|
trackPageview(properties) {
|
|
192
|
-
if (!this.
|
|
361
|
+
if (!this.canTrackAnalytics()) return;
|
|
193
362
|
this.track("$pageview", {
|
|
194
363
|
...properties
|
|
195
364
|
});
|
|
196
365
|
}
|
|
197
366
|
/** Track a custom event */
|
|
198
367
|
track(eventName, properties) {
|
|
199
|
-
if (!this.
|
|
368
|
+
if (!this.canTrackAnalytics()) return;
|
|
200
369
|
const utm = getUTMParams();
|
|
370
|
+
const mergedProperties = { ...properties || {} };
|
|
371
|
+
if (this.consent.geo && this.geoContext) {
|
|
372
|
+
mergedProperties.geo = this.geoContext;
|
|
373
|
+
}
|
|
201
374
|
const event = {
|
|
202
375
|
project_id: this.config.apiKey,
|
|
203
376
|
distinct_id: this.distinctId,
|
|
204
377
|
event_name: eventName,
|
|
205
378
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
206
|
-
properties,
|
|
379
|
+
properties: mergedProperties,
|
|
207
380
|
page_url: typeof window !== "undefined" ? window.location.href : "",
|
|
208
381
|
page_title: typeof document !== "undefined" ? document.title : "",
|
|
209
382
|
referrer: typeof document !== "undefined" ? document.referrer : "",
|
|
@@ -223,11 +396,9 @@ var Krypton = class {
|
|
|
223
396
|
this.flush();
|
|
224
397
|
}
|
|
225
398
|
}
|
|
226
|
-
/** Flush all queued events to the server */
|
|
227
399
|
async flush() {
|
|
228
400
|
await Promise.all([this.flushEvents(), this.flushHeatmapEvents()]);
|
|
229
401
|
}
|
|
230
|
-
/** Shutdown the SDK */
|
|
231
402
|
shutdown() {
|
|
232
403
|
if (this.flushTimer) {
|
|
233
404
|
clearInterval(this.flushTimer);
|
|
@@ -235,7 +406,30 @@ var Krypton = class {
|
|
|
235
406
|
}
|
|
236
407
|
this.flush();
|
|
237
408
|
}
|
|
238
|
-
|
|
409
|
+
captureGeoOnce() {
|
|
410
|
+
if (this.geoRequested) return;
|
|
411
|
+
if (!this.consent.geo) return;
|
|
412
|
+
if (typeof navigator === "undefined" || !navigator.geolocation) return;
|
|
413
|
+
this.geoRequested = true;
|
|
414
|
+
navigator.geolocation.getCurrentPosition(
|
|
415
|
+
(pos) => {
|
|
416
|
+
const round = (value, precision = 3) => Number(value.toFixed(precision));
|
|
417
|
+
this.geoContext = {
|
|
418
|
+
lat: round(pos.coords.latitude),
|
|
419
|
+
lon: round(pos.coords.longitude),
|
|
420
|
+
accuracy_m: Math.round(pos.coords.accuracy),
|
|
421
|
+
captured_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
422
|
+
};
|
|
423
|
+
},
|
|
424
|
+
() => {
|
|
425
|
+
},
|
|
426
|
+
{
|
|
427
|
+
enableHighAccuracy: false,
|
|
428
|
+
maximumAge: 10 * 60 * 1e3,
|
|
429
|
+
timeout: 5e3
|
|
430
|
+
}
|
|
431
|
+
);
|
|
432
|
+
}
|
|
239
433
|
async flushEvents() {
|
|
240
434
|
if (this.eventQueue.length === 0) return;
|
|
241
435
|
const events = this.eventQueue.splice(0, this.eventQueue.length);
|
|
@@ -278,6 +472,7 @@ var Krypton = class {
|
|
|
278
472
|
}
|
|
279
473
|
captureSnapshot() {
|
|
280
474
|
if (typeof window === "undefined" || typeof document === "undefined") return;
|
|
475
|
+
if (!this.isHeatmapFeatureEnabled()) return;
|
|
281
476
|
const currentUrl = window.location.href;
|
|
282
477
|
if (this.lastSnapshotUrl === currentUrl) return;
|
|
283
478
|
this.lastSnapshotUrl = currentUrl;
|
|
@@ -313,9 +508,11 @@ var Krypton = class {
|
|
|
313
508
|
}
|
|
314
509
|
setupHeatmap() {
|
|
315
510
|
if (typeof window === "undefined") return;
|
|
511
|
+
if (this.heatmapSetup) return;
|
|
512
|
+
this.heatmapSetup = true;
|
|
316
513
|
this.captureSnapshot();
|
|
317
514
|
document.addEventListener("click", (e) => {
|
|
318
|
-
if (!this.
|
|
515
|
+
if (!this.isHeatmapFeatureEnabled()) return;
|
|
319
516
|
const target = e.target;
|
|
320
517
|
this.heatmapQueue.push({
|
|
321
518
|
project_id: this.config.apiKey,
|
|
@@ -336,7 +533,7 @@ var Krypton = class {
|
|
|
336
533
|
let maxScrollDepth = 0;
|
|
337
534
|
let scrollTimeout = null;
|
|
338
535
|
window.addEventListener("scroll", () => {
|
|
339
|
-
if (!this.
|
|
536
|
+
if (!this.isHeatmapFeatureEnabled()) return;
|
|
340
537
|
const scrollTop = window.scrollY || document.documentElement.scrollTop;
|
|
341
538
|
const docHeight = document.documentElement.scrollHeight - window.innerHeight;
|
|
342
539
|
const depth = docHeight > 0 ? scrollTop / docHeight * 100 : 0;
|