@kryptonhq/analytics 0.1.5 → 0.1.7
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 +37 -96
- package/dist/browser.global.js +3 -7
- package/dist/index.d.mts +7 -6
- package/dist/index.d.ts +7 -6
- package/dist/index.js +47 -62
- package/dist/index.mjs +47 -62
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,136 +1,77 @@
|
|
|
1
1
|
# @kryptonhq/analytics
|
|
2
2
|
|
|
3
|
-
Krypton Analytics JavaScript SDK.
|
|
4
|
-
|
|
5
|
-
## Install (npm)
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
npm install @kryptonhq/analytics
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
```ts
|
|
12
|
-
import { Krypton } from "@kryptonhq/analytics";
|
|
13
|
-
|
|
14
|
-
const krypton = new Krypton({
|
|
15
|
-
apiKey: "kapi_xxx",
|
|
16
|
-
endpoint: "https://ingest.yourdomain.com",
|
|
17
|
-
autoPageview: true,
|
|
18
|
-
heatmap: true,
|
|
19
|
-
consentRequired: true,
|
|
20
|
-
showConsentBanner: true,
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
krypton.track("signup_clicked", { plan: "pro" });
|
|
24
|
-
```
|
|
3
|
+
Krypton Analytics JavaScript SDK — privacy-first analytics tracking.
|
|
25
4
|
|
|
26
5
|
## Install (CDN, script tag)
|
|
27
6
|
|
|
28
|
-
Use jsDelivr:
|
|
29
|
-
|
|
30
7
|
```html
|
|
31
8
|
<script defer src="https://cdn.jsdelivr.net/npm/@kryptonhq/analytics@latest/dist/browser.global.js"></script>
|
|
32
9
|
<script>
|
|
33
|
-
window.addEventListener("
|
|
34
|
-
|
|
10
|
+
window.addEventListener("load", function () {
|
|
11
|
+
window.krypton = window.KryptonAnalytics.init({
|
|
35
12
|
apiKey: "kapi_xxx",
|
|
36
13
|
endpoint: "https://ingest.yourdomain.com",
|
|
37
14
|
autoPageview: true,
|
|
38
15
|
heatmap: true,
|
|
39
16
|
consentRequired: true,
|
|
40
17
|
showConsentBanner: true
|
|
41
|
-
})
|
|
42
|
-
|
|
43
|
-
krypton.track("page_loaded");
|
|
44
|
-
});
|
|
18
|
+
})
|
|
19
|
+
})
|
|
45
20
|
</script>
|
|
46
21
|
```
|
|
47
22
|
|
|
48
23
|
The CDN build exposes a global: `window.KryptonAnalytics`.
|
|
49
24
|
|
|
50
|
-
##
|
|
51
|
-
|
|
52
|
-
The SDK supports category-level consent:
|
|
53
|
-
|
|
54
|
-
- `analytics`
|
|
55
|
-
- `heatmaps`
|
|
56
|
-
- `geo` (browser geolocation, if granted by user)
|
|
25
|
+
## Install (npm)
|
|
57
26
|
|
|
58
|
-
|
|
27
|
+
```bash
|
|
28
|
+
npm install @kryptonhq/analytics
|
|
29
|
+
```
|
|
59
30
|
|
|
60
31
|
```ts
|
|
61
|
-
import {
|
|
32
|
+
import { createKrypton } from "@kryptonhq/analytics";
|
|
62
33
|
|
|
63
|
-
const krypton =
|
|
34
|
+
const krypton = createKrypton({
|
|
64
35
|
apiKey: "kapi_xxx",
|
|
65
36
|
endpoint: "https://ingest.yourdomain.com",
|
|
37
|
+
autoPageview: true,
|
|
66
38
|
heatmap: true,
|
|
67
|
-
consentRequired: true,
|
|
68
|
-
showConsentBanner: true,
|
|
39
|
+
consentRequired: true,
|
|
40
|
+
showConsentBanner: true,
|
|
69
41
|
});
|
|
70
42
|
|
|
71
|
-
|
|
72
|
-
krypton.setConsent({
|
|
73
|
-
analytics: true,
|
|
74
|
-
heatmaps: false,
|
|
75
|
-
geo: false,
|
|
76
|
-
});
|
|
43
|
+
krypton.track("signup", { plan: "pro" });
|
|
77
44
|
```
|
|
78
45
|
|
|
79
|
-
|
|
46
|
+
## Consent (default deny + categories)
|
|
80
47
|
|
|
81
|
-
|
|
82
|
-
<script>
|
|
83
|
-
(function (w, d, s, u, n) {
|
|
84
|
-
w[n] = w[n] || function () { (w[n].q = w[n].q || []).push(arguments); };
|
|
85
|
-
w[n].l = +new Date();
|
|
86
|
-
var js = d.createElement(s), fjs = d.getElementsByTagName(s)[0];
|
|
87
|
-
js.async = 1;
|
|
88
|
-
js.src = u;
|
|
89
|
-
js.onload = function () {
|
|
90
|
-
var cfg = w[n].cfg;
|
|
91
|
-
w[n].client = w.KryptonAnalytics.init(cfg);
|
|
92
|
-
var q = w[n].q || [];
|
|
93
|
-
for (var i = 0; i < q.length; i++) {
|
|
94
|
-
var args = q[i];
|
|
95
|
-
if (args[0] === "track") w[n].client.track(args[1], args[2]);
|
|
96
|
-
}
|
|
97
|
-
};
|
|
98
|
-
fjs.parentNode.insertBefore(js, fjs);
|
|
99
|
-
})(window, document, "script", "https://cdn.jsdelivr.net/npm/@kryptonhq/analytics@latest/dist/browser.global.js", "krypton");
|
|
100
|
-
|
|
101
|
-
krypton.cfg = {
|
|
102
|
-
apiKey: "kapi_xxx",
|
|
103
|
-
endpoint: "https://ingest.yourdomain.com",
|
|
104
|
-
autoPageview: true,
|
|
105
|
-
heatmap: true
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
krypton("track", "landing_view");
|
|
109
|
-
</script>
|
|
110
|
-
```
|
|
48
|
+
The SDK supports category-level consent:
|
|
111
49
|
|
|
112
|
-
|
|
50
|
+
- `analytics` — pageviews and custom events
|
|
51
|
+
- `heatmaps` — click and scroll interaction maps
|
|
113
52
|
|
|
114
|
-
|
|
53
|
+
When `consentRequired: true` and `showConsentBanner: true`, a built-in consent popup is shown automatically. No data is collected until the user grants consent.
|
|
115
54
|
|
|
116
|
-
-
|
|
55
|
+
Geolocation is resolved server-side from the request IP (no browser Geolocation API needed).
|
|
117
56
|
|
|
118
|
-
|
|
57
|
+
### Manual consent control
|
|
119
58
|
|
|
120
|
-
|
|
121
|
-
|
|
59
|
+
```ts
|
|
60
|
+
krypton.setConsent({ analytics: true, heatmaps: false });
|
|
122
61
|
|
|
123
|
-
|
|
62
|
+
krypton.grantConsent(); // grant all
|
|
63
|
+
krypton.revokeConsent(); // revoke all
|
|
124
64
|
|
|
125
|
-
|
|
65
|
+
krypton.showConsentBanner(); // re-show the popup
|
|
66
|
+
```
|
|
126
67
|
|
|
127
|
-
|
|
68
|
+
## API
|
|
128
69
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
70
|
+
```ts
|
|
71
|
+
krypton.track("event_name", { key: "value" });
|
|
72
|
+
krypton.trackPageview();
|
|
73
|
+
krypton.identify("user-123");
|
|
74
|
+
krypton.flush();
|
|
75
|
+
krypton.shutdown();
|
|
76
|
+
krypton.getConsent(); // { analytics: boolean, heatmaps: boolean }
|
|
77
|
+
```
|
package/dist/browser.global.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
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})},xe=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of Se(t))!be.call(e,i)&&i!==r&&Z(e,i,{get:()=>t[i],enumerable:!(n=ke(t,i))||n.enumerable});return e};var Ie=e=>xe(Z({},"__esModule",{value:!0}),e);var at={};Ce(at,{Krypton:()=>q,default:()=>it,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 n=(r=this.getMeta(t))===null||r===void 0?void 0:r.id;return n??-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,n=this.getId(t);this.idNodeMap.delete(n),t.childNodes&&t.childNodes.forEach(function(i){return r.removeNodeFromMap(i)})},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 n=r.id;this.idNodeMap.set(n,t),this.nodeMetaMap.set(t,r)},e.prototype.replace=function(t,r){var n=this.getNode(t);if(n){var i=this.nodeMetaMap.get(n);i&&this.nodeMetaMap.set(r,i)}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,n=e.type,i=e.value,a=e.maskInputFn,c=i||"";return(t[r.toLowerCase()]||t[n])&&(a?c=a(c):c="*".repeat(c.length)),c}var le="__rrweb_original__";function Ae(e){var t=e.getContext("2d");if(!t)return!0;for(var r=50,n=0;n<e.width;n+=r)for(var i=0;i<e.height;i+=r){var a=t.getImageData,c=le in a?a[le]:a,u=new Uint32Array(c.call(t,n,i,Math.min(r,e.width-n),Math.min(r,e.height-i)).data.buffer);if(u.some(function(o){return o!==0}))return!1}return!0}var Me=1,Pe=new RegExp("[^a-z0-9-_:]"),ue=-2;function De(){return Me++}function Fe(e){if(e instanceof HTMLFormElement)return"form";var t=e.tagName.toLowerCase().trim();return Pe.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,Be=/^(?!www\.|(?:http|ftp)s?:\/\/|[A-Za-z]:\\|\/\/|#).*/,Ke=/^(data:)([^,]*),(.*)/i;function Q(e,t){return(e||"").replace(We,function(r,n,i,a,c,u){var o=i||c||u,f=n||a||"";if(!o)return r;if(!Be.test(o)||Ke.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,w=h;b<w.length;b++){var k=w[b];k!=="."&&(k===".."?l.pop():l.push(k))}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 n(f){var l,h=f.exec(t.substring(r));return h?(l=h[0],r+=l.length,l):""}for(var i=[];n(je),!(r>=t.length);){var a=n(ze);if(a.slice(-1)===",")a=j(e,a.substring(0,a.length-1)),i.push(a);else{var c="";a=j(e,a);for(var u=!1;;){var o=t.charAt(r);if(o===""){i.push((a+c).trim());break}else if(u)o===")"&&(u=!1);else if(o===","){r+=1,i.push((a+c).trim());break}else o==="("&&(u=!0);c+=o,r+=1}}}return i.join(", ")}function j(e,t){if(!t||t.trim()==="")return t;var r=e.createElement("a");return r.href=t,r.href}function $e(e){return!!(e.tagName==="svg"||e.ownerSVGElement)}function ne(){var e=document.createElement("a");return e.href="",e.href}function Ge(e,t,r,n){return r==="src"||r==="href"&&n&&!(t==="use"&&n[0]==="#")||r==="xlink:href"&&n&&n[0]!=="#"||r==="background"&&n&&(t==="table"||t==="td"||t==="th")?j(e,n):r==="srcset"&&n?qe(e,n):r==="style"&&n?Q(n,ne()):t==="object"&&r==="data"&&n?j(e,n):n}function Qe(e,t,r){if(typeof t=="string"){if(e.classList.contains(t))return!0}else for(var n=e.classList.length;n--;){var i=e.classList[n];if(t.test(i))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 n=e.classList.length;n--;){var i=e.classList[n];if(t.test(i))return!0}return r?re(e.parentNode,t,r):!1}function Je(e,t,r){var n=e.nodeType===e.ELEMENT_NODE?e:e.parentElement;if(n===null)return!1;if(typeof t=="string"){if(n.classList.contains(t)||n.closest(".".concat(t)))return!0}else if(re(n,t,!0))return!0;return!!(r&&(n.matches(r)||n.closest(r)))}function Ve(e,t,r){var n=e.contentWindow;if(n){var i=!1,a;try{a=n.document.readyState}catch{return}if(a!=="complete"){var c=setTimeout(function(){i||(t(),i=!0)},r);e.addEventListener("load",function(){clearTimeout(c),i=!0,t()});return}var u="about:blank";if(n.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 n=!1,i;try{i=e.sheet}catch{return}if(!i){var a=setTimeout(function(){n||(t(),n=!0)},r);e.addEventListener("load",function(){clearTimeout(a),n=!0,t()})}}function Xe(e,t){var r=t.doc,n=t.mirror,i=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,w=t.dataURLOptions,k=w===void 0?{}:w,x=t.inlineImages,I=t.recordCanvas,T=t.keepIframeSrcFn,p=t.newlyAddedElement,s=p===void 0?!1:p,y=Ze(r,n);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:i,blockSelector:a,inlineStylesheet:o,maskInputOptions:l,maskInputFn:b,dataURLOptions:k,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,n=t.maskTextClass,i=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=Q(o,ne())}return l&&(o="SCRIPT_PLACEHOLDER"),!f&&!l&&o&&Je(e,n,i)&&(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,n=t.blockClass,i=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,w=t.keepIframeSrcFn,k=t.newlyAddedElement,x=k===void 0?!1:k,I=t.rootId,T=Qe(e,n,i),p=Fe(e),s={},y=e.attributes.length,A=0;A<y;A++){var E=e.attributes[A];s[E.name]=Ge(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=Q(m,C.href))}if(p==="style"&&e.sheet&&!(e.innerText||e.textContent||"").trim().length){var m=te(e.sheet);m&&(s._cssText=Q(m,ne()))}if(p==="input"||p==="textarea"||p==="select"){var F=e.value,_=e.checked;s.type!=="radio"&&s.type!=="checkbox"&&s.type!=="submit"&&s.type!=="button"&&F?s.value=Oe({type:s.type,tagName:p,value:F,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")Ae(e)||(s.rr_dataURL=e.toDataURL(l.type,l.quality));else if(!("__context"in e)){var L=e.toDataURL(l.type,l.quality),M=document.createElement("canvas");M.width=e.width,M.height=e.height;var P=M.toDataURL(l.type,l.quality);L!==P&&(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 D=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?D():S.onload=D}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"&&!w(s.src)&&(e.contentDocument||(s.rr_src=s.src),delete s.src),{type:v.Element,tagName:p,attributes:s,childNodes:[],isSVG:$e(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 G(e,t){var r=t.doc,n=t.mirror,i=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,w=b===void 0?{}:b,k=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,A=t.recordCanvas,E=A===void 0?!1:A,C=t.onSerialize,m=t.onIframeLoad,F=t.iframeLoadTimeout,_=F===void 0?5e3:F,L=t.onStylesheetLoad,M=t.stylesheetLoadTimeout,P=M===void 0?5e3:M,S=t.keepIframeSrcFn,N=S===void 0?function(){return!1}:S,D=t.newlyAddedElement,U=D===void 0?!1:D,W=t.preserveWhiteSpace,O=W===void 0?!0:W,R=Xe(e,{doc:r,mirror:n,blockClass:i,blockSelector:a,maskTextClass:c,maskTextSelector:u,inlineStylesheet:h,maskInputOptions:w,maskTextFn:k,maskInputFn:x,dataURLOptions:p,inlineImages:y,recordCanvas:E,keepIframeSrcFn:N,newlyAddedElement:U});if(!R)return console.warn(e,"not serialized"),null;var $;n.hasNode(e)?$=n.getId(e):rt(R,I)||!O&&R.type===v.Text&&!R.isStyle&&!R.textContent.replace(/^\s+|\s+$/gm,"").length?$=ue:$=De();var g=Object.assign(R,{id:$});if(n.add(e,g),$===ue)return null;C&&C(e);var J=!f;if(g.type===v.Element){J=J&&!g.needBlock,delete g.needBlock;var ie=e.shadowRoot;ie&&ee(ie)&&(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:n,blockClass:i,blockSelector:a,maskTextClass:c,maskTextSelector:u,skipChild:f,inlineStylesheet:h,maskInputOptions:w,maskTextFn:k,maskInputFn:x,slimDOMOptions:I,dataURLOptions:p,inlineImages:y,recordCanvas:E,preserveWhiteSpace:O,onSerialize:C,onIframeLoad:m,iframeLoadTimeout:_,onStylesheetLoad:L,stylesheetLoadTimeout:P,keepIframeSrcFn:N},V=0,oe=Array.from(e.childNodes);V<oe.length;V++){var Y=oe[V],B=G(Y,ae);B&&g.childNodes.push(B)}if(Te(e)&&e.shadowRoot)for(var X=0,se=Array.from(e.shadowRoot.childNodes);X<se.length;X++){var Y=se[X],B=G(Y,ae);B&&(ee(e.shadowRoot)&&(B.isShadow=!0),g.childNodes.push(B))}}return e.parentNode&&Ee(e.parentNode)&&ee(e.parentNode)&&(g.isShadow=!0),g.type===v.Element&&g.tagName==="iframe"&&Ve(e,function(){var K=e.contentDocument;if(K&&m){var ce=G(K,{doc:K,mirror:n,blockClass:i,blockSelector:a,maskTextClass:c,maskTextSelector:u,skipChild:!1,inlineStylesheet:h,maskInputOptions:w,maskTextFn:k,maskInputFn:x,slimDOMOptions:I,dataURLOptions:p,inlineImages:y,recordCanvas:E,preserveWhiteSpace:O,onSerialize:C,onIframeLoad:m,iframeLoadTimeout:_,onStylesheetLoad:L,stylesheetLoadTimeout:P,keepIframeSrcFn:N});ce&&m(e,ce)}},_),g.type===v.Element&&g.tagName==="link"&&g.attributes.rel==="stylesheet"&&Ye(e,function(){if(L){var K=G(e,{doc:r,mirror:n,blockClass:i,blockSelector:a,maskTextClass:c,maskTextSelector:u,skipChild:!1,inlineStylesheet:h,maskInputOptions:w,maskTextFn:k,maskInputFn:x,slimDOMOptions:I,dataURLOptions:p,inlineImages:y,recordCanvas:E,preserveWhiteSpace:O,onSerialize:C,onIframeLoad:m,iframeLoadTimeout:_,onStylesheetLoad:L,stylesheetLoadTimeout:P,keepIframeSrcFn:N});K&&L(e,K)}},P),g}function de(e,t){var r=t||{},n=r.mirror,i=n===void 0?new Ne:n,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,w=r.inlineStylesheet,k=w===void 0?!0:w,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,A=r.maskTextFn,E=r.maskInputFn,C=r.slimDOM,m=C===void 0?!1:C,F=r.dataURLOptions,_=r.preserveWhiteSpace,L=r.onSerialize,M=r.onIframeLoad,P=r.iframeLoadTimeout,S=r.onStylesheetLoad,N=r.stylesheetLoadTimeout,D=r.keepIframeSrcFn,U=D===void 0?function(){return!1}:D,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 G(e,{doc:e,mirror:i,blockClass:c,blockSelector:o,maskTextClass:l,maskTextSelector:b,skipChild:!1,inlineStylesheet:k,maskInputOptions:W,maskTextFn:A,maskInputFn:E,slimDOMOptions:O,dataURLOptions:F,inlineImages:I,recordCanvas:p,preserveWhiteSpace:_,onSerialize:L,onIframeLoad:M,iframeLoadTimeout:P,onStylesheetLoad:S,stylesheetLoadTimeout:N,keepIframeSrcFn:U,newlyAddedElement:!1})}var nt=/([^\\]):hover/,st=new RegExp(nt.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";try{if(typeof sessionStorage<"u"){let t=sessionStorage.getItem(e);return t||(t=H(),sessionStorage.setItem(e,t)),t}}catch{}return H()}function he(){let e="_krypton_did";try{if(typeof localStorage<"u"){let t=localStorage.getItem(e);return t||(t=H(),localStorage.setItem(e,t)),t}}catch{}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 n=e.get(r);n&&(t[r]=n)}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 n=r.tagName.toLowerCase();if(r.id){t.unshift(`#${r.id}`);break}if(r.className&&typeof r.className=="string"){let i=r.className.trim().split(/\s+/).slice(0,2).join(".");i&&(n+=`.${i}`)}t.unshift(n),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.logPrefix="[Krypton SDK]";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().finally(()=>{try{this.setupTracking()}catch(t){this.warn("setupTracking failed",t)}try{this.config.consentRequired&&this.config.showConsentBanner&&!this.hasStoredConsent()&&this.showConsentBannerWhenReady()}catch(t){this.warn("consent banner initialization failed",t)}}))}showConsentBannerWhenReady(t=12){if(!(typeof document>"u")&&!document.getElementById("krypton-consent-banner")){if(document.body){this.showConsentBanner();return}t<=0||setTimeout(()=>this.showConsentBannerWhenReady(t-1),50)}}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(){try{return typeof localStorage>"u"?!1:!!localStorage.getItem(this.consentStorageKey())}catch{return!1}}loadStoredConsent(){try{if(typeof localStorage>"u")return null;let t=localStorage.getItem(this.consentStorageKey());if(!t)return null;let r=JSON.parse(t);return{analytics:!!r.analytics,heatmaps:!!r.heatmaps,geo:!!r.geo}}catch{return null}}persistConsent(){try{if(typeof localStorage>"u")return;localStorage.setItem(this.consentStorageKey(),JSON.stringify(this.consent))}catch{}}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=null;try{r=sessionStorage.getItem(t)}catch{r=null}if(r)try{let n=JSON.parse(r);if(n._ts&&Date.now()-n._ts<300*1e3){this.serverConfig=n,this.configFetched=!0;return}}catch{}try{let n=new AbortController,i=setTimeout(()=>n.abort(),5e3),a=await fetch(`${this.config.endpoint}/api/v1/config?api_key=${encodeURIComponent(this.config.apiKey)}`,{signal:n.signal});if(clearTimeout(i),a.ok){let c=await a.json();this.serverConfig=c,this.configFetched=!0;try{sessionStorage.setItem(t,JSON.stringify({...c,_ts:Date.now()}))}catch{}}}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=(...n)=>{try{t.apply(history,n),this.config.autoPageview&&this.canTrackAnalytics()&&setTimeout(()=>this.trackPageview(),0),this.isHeatmapFeatureEnabled()&&setTimeout(()=>this.captureSnapshot(),0)}catch(i){this.warn("pushState hook failed",i)}};let r=history.replaceState;history.replaceState=(...n)=>{try{r.apply(history,n),this.config.autoPageview&&this.canTrackAnalytics()&&setTimeout(()=>this.trackPageview(),0),this.isHeatmapFeatureEnabled()&&setTimeout(()=>this.captureSnapshot(),0)}catch(i){this.warn("replaceState hook failed",i)}},window.addEventListener("popstate",()=>{try{this.config.autoPageview&&this.canTrackAnalytics()&&setTimeout(()=>this.trackPageview(),0),this.isHeatmapFeatureEnabled()&&setTimeout(()=>this.captureSnapshot(),0)}catch(n){this.warn("popstate hook failed",n)}}),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=`
|
|
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})},xe=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of Se(t))!be.call(e,i)&&i!==r&&Z(e,i,{get:()=>t[i],enumerable:!(n=ke(t,i))||n.enumerable});return e};var Ie=e=>xe(Z({},"__esModule",{value:!0}),e);var at={};Ce(at,{Krypton:()=>q,default:()=>it,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(Ne(e))try{t=te(e.styleSheet)||t}catch{}return t}function Ne(e){return"styleSheet"in e}var _e=(function(){function e(){this.idNodeMap=new Map,this.nodeMetaMap=new WeakMap}return e.prototype.getId=function(t){var r;if(!t)return-1;var n=(r=this.getMeta(t))===null||r===void 0?void 0:r.id;return n??-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,n=this.getId(t);this.idNodeMap.delete(n),t.childNodes&&t.childNodes.forEach(function(i){return r.removeNodeFromMap(i)})},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 n=r.id;this.idNodeMap.set(n,t),this.nodeMetaMap.set(t,r)},e.prototype.replace=function(t,r){var n=this.getNode(t);if(n){var i=this.nodeMetaMap.get(n);i&&this.nodeMetaMap.set(r,i)}this.idNodeMap.set(t,r)},e.prototype.reset=function(){this.idNodeMap=new Map,this.nodeMetaMap=new WeakMap},e})();function Ae(e){var t=e.maskInputOptions,r=e.tagName,n=e.type,i=e.value,a=e.maskInputFn,c=i||"";return(t[r.toLowerCase()]||t[n])&&(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,n=0;n<e.width;n+=r)for(var i=0;i<e.height;i+=r){var a=t.getImageData,c=le in a?a[le]:a,u=new Uint32Array(c.call(t,n,i,Math.min(r,e.width-n),Math.min(r,e.height-i)).data.buffer);if(u.some(function(o){return o!==0}))return!1}return!0}var Oe=1,Pe=new RegExp("[^a-z0-9-_:]"),ue=-2;function De(){return Oe++}function Fe(e){if(e instanceof HTMLFormElement)return"form";var t=e.tagName.toLowerCase().trim();return Pe.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,Be=/^(?!www\.|(?:http|ftp)s?:\/\/|[A-Za-z]:\\|\/\/|#).*/,Ke=/^(data:)([^,]*),(.*)/i;function G(e,t){return(e||"").replace(We,function(r,n,i,a,c,u){var o=i||c||u,f=n||a||"";if(!o)return r;if(!Be.test(o)||Ke.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("/"),p=o.split("/");l.pop();for(var b=0,w=p;b<w.length;b++){var k=w[b];k!=="."&&(k===".."?l.pop():l.push(k))}return"url(".concat(f).concat(l.join("/")).concat(f,")")})}var ze=/^[^ \t\n\r\u000c]+/,$e=/^[, \t\n\r\u000c]+/;function qe(e,t){if(t.trim()==="")return t;var r=0;function n(f){var l,p=f.exec(t.substring(r));return p?(l=p[0],r+=l.length,l):""}for(var i=[];n($e),!(r>=t.length);){var a=n(ze);if(a.slice(-1)===",")a=$(e,a.substring(0,a.length-1)),i.push(a);else{var c="";a=$(e,a);for(var u=!1;;){var o=t.charAt(r);if(o===""){i.push((a+c).trim());break}else if(u)o===")"&&(u=!1);else if(o===","){r+=1,i.push((a+c).trim());break}else o==="("&&(u=!0);c+=o,r+=1}}}return i.join(", ")}function $(e,t){if(!t||t.trim()==="")return t;var r=e.createElement("a");return r.href=t,r.href}function je(e){return!!(e.tagName==="svg"||e.ownerSVGElement)}function ne(){var e=document.createElement("a");return e.href="",e.href}function Qe(e,t,r,n){return r==="src"||r==="href"&&n&&!(t==="use"&&n[0]==="#")||r==="xlink:href"&&n&&n[0]!=="#"||r==="background"&&n&&(t==="table"||t==="td"||t==="th")?$(e,n):r==="srcset"&&n?qe(e,n):r==="style"&&n?G(n,ne()):t==="object"&&r==="data"&&n?$(e,n):n}function Ge(e,t,r){if(typeof t=="string"){if(e.classList.contains(t))return!0}else for(var n=e.classList.length;n--;){var i=e.classList[n];if(t.test(i))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 n=e.classList.length;n--;){var i=e.classList[n];if(t.test(i))return!0}return r?re(e.parentNode,t,r):!1}function Je(e,t,r){var n=e.nodeType===e.ELEMENT_NODE?e:e.parentElement;if(n===null)return!1;if(typeof t=="string"){if(n.classList.contains(t)||n.closest(".".concat(t)))return!0}else if(re(n,t,!0))return!0;return!!(r&&(n.matches(r)||n.closest(r)))}function Ve(e,t,r){var n=e.contentWindow;if(n){var i=!1,a;try{a=n.document.readyState}catch{return}if(a!=="complete"){var c=setTimeout(function(){i||(t(),i=!0)},r);e.addEventListener("load",function(){clearTimeout(c),i=!0,t()});return}var u="about:blank";if(n.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 n=!1,i;try{i=e.sheet}catch{return}if(!i){var a=setTimeout(function(){n||(t(),n=!0)},r);e.addEventListener("load",function(){clearTimeout(a),n=!0,t()})}}function Xe(e,t){var r=t.doc,n=t.mirror,i=t.blockClass,a=t.blockSelector,c=t.maskTextClass,u=t.maskTextSelector,o=t.inlineStylesheet,f=t.maskInputOptions,l=f===void 0?{}:f,p=t.maskTextFn,b=t.maskInputFn,w=t.dataURLOptions,k=w===void 0?{}:w,x=t.inlineImages,I=t.recordCanvas,T=t.keepIframeSrcFn,h=t.newlyAddedElement,s=h===void 0?!1:h,y=Ze(r,n);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:i,blockSelector:a,inlineStylesheet:o,maskInputOptions:l,maskInputFn:b,dataURLOptions:k,inlineImages:x,recordCanvas:I,keepIframeSrcFn:T,newlyAddedElement:s,rootId:y});case e.TEXT_NODE:return et(e,{maskTextClass:c,maskTextSelector:u,maskTextFn:p,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,n=t.maskTextClass,i=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(p){console.warn("Cannot get CSS styles from text's parentNode. Error: ".concat(p),e)}o=G(o,ne())}return l&&(o="SCRIPT_PLACEHOLDER"),!f&&!l&&o&&Je(e,n,i)&&(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,n=t.blockClass,i=t.blockSelector,a=t.inlineStylesheet,c=t.maskInputOptions,u=c===void 0?{}:c,o=t.maskInputFn,f=t.dataURLOptions,l=f===void 0?{}:f,p=t.inlineImages,b=t.recordCanvas,w=t.keepIframeSrcFn,k=t.newlyAddedElement,x=k===void 0?!1:k,I=t.rootId,T=Ge(e,n,i),h=Fe(e),s={},y=e.attributes.length,M=0;M<y;M++){var E=e.attributes[M];s[E.name]=Qe(r,h,E.name,E.value)}if(h==="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=G(m,C.href))}if(h==="style"&&e.sheet&&!(e.innerText||e.textContent||"").trim().length){var m=te(e.sheet);m&&(s._cssText=G(m,ne()))}if(h==="input"||h==="textarea"||h==="select"){var F=e.value,N=e.checked;s.type!=="radio"&&s.type!=="checkbox"&&s.type!=="submit"&&s.type!=="button"&&F?s.value=Ae({type:s.type,tagName:h,value:F,maskInputOptions:u,maskInputFn:o}):N&&(s.checked=N)}if(h==="option"&&(e.selected&&!u.select?s.selected=!0:delete s.selected),h==="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),O=document.createElement("canvas");O.width=e.width,O.height=e.height;var P=O.toDataURL(l.type,l.quality);L!==P&&(s.rr_dataURL=L)}}if(h==="img"&&p){z||(z=r.createElement("canvas"),fe=z.getContext("2d"));var S=e,_=S.crossOrigin;S.crossOrigin="anonymous";var D=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))}_?s.crossOrigin=_:S.removeAttribute("crossorigin")};S.complete&&S.naturalWidth!==0?D():S.onload=D}if((h==="audio"||h==="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,A=U.height;s={class:s.class,rr_width:"".concat(W,"px"),rr_height:"".concat(A,"px")}}return h==="iframe"&&!w(s.src)&&(e.contentDocument||(s.rr_src=s.src),delete s.src),{type:v.Element,tagName:h,attributes:s,childNodes:[],isSVG:je(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,n=t.mirror,i=t.blockClass,a=t.blockSelector,c=t.maskTextClass,u=t.maskTextSelector,o=t.skipChild,f=o===void 0?!1:o,l=t.inlineStylesheet,p=l===void 0?!0:l,b=t.maskInputOptions,w=b===void 0?{}:b,k=t.maskTextFn,x=t.maskInputFn,I=t.slimDOMOptions,T=t.dataURLOptions,h=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,F=t.iframeLoadTimeout,N=F===void 0?5e3:F,L=t.onStylesheetLoad,O=t.stylesheetLoadTimeout,P=O===void 0?5e3:O,S=t.keepIframeSrcFn,_=S===void 0?function(){return!1}:S,D=t.newlyAddedElement,U=D===void 0?!1:D,W=t.preserveWhiteSpace,A=W===void 0?!0:W,R=Xe(e,{doc:r,mirror:n,blockClass:i,blockSelector:a,maskTextClass:c,maskTextSelector:u,inlineStylesheet:p,maskInputOptions:w,maskTextFn:k,maskInputFn:x,dataURLOptions:h,inlineImages:y,recordCanvas:E,keepIframeSrcFn:_,newlyAddedElement:U});if(!R)return console.warn(e,"not serialized"),null;var j;n.hasNode(e)?j=n.getId(e):rt(R,I)||!A&&R.type===v.Text&&!R.isStyle&&!R.textContent.replace(/^\s+|\s+$/gm,"").length?j=ue:j=De();var g=Object.assign(R,{id:j});if(n.add(e,g),j===ue)return null;C&&C(e);var J=!f;if(g.type===v.Element){J=J&&!g.needBlock,delete g.needBlock;var ie=e.shadowRoot;ie&&ee(ie)&&(g.isShadowHost=!0)}if((g.type===v.Document||g.type===v.Element)&&J){I.headWhitespace&&g.type===v.Element&&g.tagName==="head"&&(A=!1);for(var ae={doc:r,mirror:n,blockClass:i,blockSelector:a,maskTextClass:c,maskTextSelector:u,skipChild:f,inlineStylesheet:p,maskInputOptions:w,maskTextFn:k,maskInputFn:x,slimDOMOptions:I,dataURLOptions:h,inlineImages:y,recordCanvas:E,preserveWhiteSpace:A,onSerialize:C,onIframeLoad:m,iframeLoadTimeout:N,onStylesheetLoad:L,stylesheetLoadTimeout:P,keepIframeSrcFn:_},V=0,oe=Array.from(e.childNodes);V<oe.length;V++){var Y=oe[V],B=Q(Y,ae);B&&g.childNodes.push(B)}if(Te(e)&&e.shadowRoot)for(var X=0,se=Array.from(e.shadowRoot.childNodes);X<se.length;X++){var Y=se[X],B=Q(Y,ae);B&&(ee(e.shadowRoot)&&(B.isShadow=!0),g.childNodes.push(B))}}return e.parentNode&&Ee(e.parentNode)&&ee(e.parentNode)&&(g.isShadow=!0),g.type===v.Element&&g.tagName==="iframe"&&Ve(e,function(){var K=e.contentDocument;if(K&&m){var ce=Q(K,{doc:K,mirror:n,blockClass:i,blockSelector:a,maskTextClass:c,maskTextSelector:u,skipChild:!1,inlineStylesheet:p,maskInputOptions:w,maskTextFn:k,maskInputFn:x,slimDOMOptions:I,dataURLOptions:h,inlineImages:y,recordCanvas:E,preserveWhiteSpace:A,onSerialize:C,onIframeLoad:m,iframeLoadTimeout:N,onStylesheetLoad:L,stylesheetLoadTimeout:P,keepIframeSrcFn:_});ce&&m(e,ce)}},N),g.type===v.Element&&g.tagName==="link"&&g.attributes.rel==="stylesheet"&&Ye(e,function(){if(L){var K=Q(e,{doc:r,mirror:n,blockClass:i,blockSelector:a,maskTextClass:c,maskTextSelector:u,skipChild:!1,inlineStylesheet:p,maskInputOptions:w,maskTextFn:k,maskInputFn:x,slimDOMOptions:I,dataURLOptions:h,inlineImages:y,recordCanvas:E,preserveWhiteSpace:A,onSerialize:C,onIframeLoad:m,iframeLoadTimeout:N,onStylesheetLoad:L,stylesheetLoadTimeout:P,keepIframeSrcFn:_});K&&L(e,K)}},P),g}function de(e,t){var r=t||{},n=r.mirror,i=n===void 0?new _e:n,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,p=r.maskTextSelector,b=p===void 0?null:p,w=r.inlineStylesheet,k=w===void 0?!0:w,x=r.inlineImages,I=x===void 0?!1:x,T=r.recordCanvas,h=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,F=r.dataURLOptions,N=r.preserveWhiteSpace,L=r.onSerialize,O=r.onIframeLoad,P=r.iframeLoadTimeout,S=r.onStylesheetLoad,_=r.stylesheetLoadTimeout,D=r.keepIframeSrcFn,U=D===void 0?function(){return!1}:D,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,A=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:i,blockClass:c,blockSelector:o,maskTextClass:l,maskTextSelector:b,skipChild:!1,inlineStylesheet:k,maskInputOptions:W,maskTextFn:M,maskInputFn:E,slimDOMOptions:A,dataURLOptions:F,inlineImages:I,recordCanvas:h,preserveWhiteSpace:N,onSerialize:L,onIframeLoad:O,iframeLoadTimeout:P,onStylesheetLoad:S,stylesheetLoadTimeout:_,keepIframeSrcFn:U,newlyAddedElement:!1})}var nt=/([^\\]):hover/,st=new RegExp(nt.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 he(){let e="_krypton_sid";try{if(typeof sessionStorage<"u"){let t=sessionStorage.getItem(e);return t||(t=H(),sessionStorage.setItem(e,t)),t}}catch{}return H()}function pe(){let e="_krypton_did";try{if(typeof localStorage<"u"){let t=localStorage.getItem(e);return t||(t=H(),localStorage.setItem(e,t)),t}}catch{}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 n=e.get(r);n&&(t[r]=n)}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 n=r.tagName.toLowerCase();if(r.id){t.unshift(`#${r.id}`);break}if(r.className&&typeof r.className=="string"){let i=r.className.trim().split(/\s+/).slice(0,2).join(".");i&&(n+=`.${i}`)}t.unshift(n),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.serverConfig=null;this.configFetched=!1;this.logPrefix="[Krypton SDK]";this.config={autoPageview:!0,heatmap:!1,consentRequired:!1,showConsentBanner:!1,consentCategories:{},flushInterval:5e3,batchSize:20,debug:!1,disableConfigCache:!1,...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().finally(()=>{try{this.setupTracking()}catch(t){this.warn("setupTracking failed",t)}try{this.config.consentRequired&&this.config.showConsentBanner&&!this.hasStoredConsent()?(this.debug("showing consent banner automatically",{consentRequired:this.config.consentRequired,showConsentBanner:this.config.showConsentBanner}),this.showConsentBannerWhenReady()):this.debug("skipping consent banner",{consentRequired:this.config.consentRequired,showConsentBanner:this.config.showConsentBanner,hasStoredConsent:this.hasStoredConsent()})}catch(t){this.warn("consent banner initialization failed",t)}}))}showConsentBannerWhenReady(t=12){if(!(typeof document>"u")&&!document.getElementById("krypton-consent-banner")){if(document.body){this.showConsentBanner();return}t<=0||setTimeout(()=>this.showConsentBannerWhenReady(t-1),50)}}resolveInitialConsent(){let t=this.loadStoredConsent();return t||{...this.config.consentRequired?{analytics:!1,heatmaps:!1}:{analytics:!0,heatmaps:!!this.config.heatmap},...this.config.consentCategories}}consentStorageKey(){return`_krypton_consent_${this.config.apiKey}`}hasStoredConsent(){try{return typeof localStorage>"u"?!1:!!localStorage.getItem(this.consentStorageKey())}catch{return!1}}loadStoredConsent(){try{if(typeof localStorage>"u")return null;let t=localStorage.getItem(this.consentStorageKey());if(!t)return null;let r=JSON.parse(t);return{analytics:!!r.analytics,heatmaps:!!r.heatmaps}}catch{return null}}persistConsent(){try{if(typeof localStorage>"u")return;localStorage.setItem(this.consentStorageKey(),JSON.stringify(this.consent))}catch{}}promotePersistentIds(){this.distinctId=pe(),this.sessionId=he()}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=null;if(!this.config.disableConfigCache)try{r=sessionStorage.getItem(t)}catch{r=null}if(r)try{let n=JSON.parse(r);if(n._ts&&Date.now()-n._ts<300*1e3){this.serverConfig=n,this.configFetched=!0,this.debug("config loaded from session cache",n);return}}catch{}try{let n=new AbortController,i=setTimeout(()=>n.abort(),5e3),a=await fetch(`${this.config.endpoint}/api/v1/config?api_key=${encodeURIComponent(this.config.apiKey)}`,{signal:n.signal});if(clearTimeout(i),a.ok){let c=await a.json();if(this.serverConfig=c,this.configFetched=!0,this.debug("config fetched from API",c),!this.config.disableConfigCache)try{sessionStorage.setItem(t,JSON.stringify({...c,_ts:Date.now()}))}catch{}}else this.warn(`Config fetch failed (${a.status})`,{endpoint:this.config.endpoint})}catch(n){this.warn("Config fetch failed",n)}}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=(...n)=>{try{t.apply(history,n),this.config.autoPageview&&this.canTrackAnalytics()&&setTimeout(()=>this.trackPageview(),0),this.isHeatmapFeatureEnabled()&&setTimeout(()=>this.captureSnapshot(),0)}catch(i){this.warn("pushState hook failed",i)}};let r=history.replaceState;history.replaceState=(...n)=>{try{r.apply(history,n),this.config.autoPageview&&this.canTrackAnalytics()&&setTimeout(()=>this.trackPageview(),0),this.isHeatmapFeatureEnabled()&&setTimeout(()=>this.captureSnapshot(),0)}catch(i){this.warn("replaceState hook failed",i)}},window.addEventListener("popstate",()=>{try{this.config.autoPageview&&this.canTrackAnalytics()&&setTimeout(()=>this.trackPageview(),0),this.isHeatmapFeatureEnabled()&&setTimeout(()=>this.captureSnapshot(),0)}catch(n){this.warn("popstate hook failed",n)}}),this.isHeatmapFeatureEnabled()&&this.setupHeatmap()}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
2
|
<div style="font-weight:600;margin-bottom:6px">Privacy preferences</div>
|
|
3
3
|
<div style="opacity:0.9;margin-bottom:10px">Choose what data you allow us to collect.</div>
|
|
4
4
|
<label style="display:flex;gap:8px;align-items:flex-start;margin:6px 0">
|
|
@@ -9,13 +9,9 @@
|
|
|
9
9
|
<input type="checkbox" id="krypton-consent-heatmaps" ${r(this.consent.heatmaps)} />
|
|
10
10
|
<span><strong>Heatmaps</strong> (click and scroll interaction maps)</span>
|
|
11
11
|
</label>
|
|
12
|
-
<
|
|
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">
|
|
12
|
+
<div style="display:flex;gap:8px;flex-wrap:wrap;margin-top:12px">
|
|
17
13
|
<button id="krypton-consent-save" style="border:0;background:#2563eb;color:#fff;padding:8px 12px;border-radius:8px;cursor:pointer">Accept selected</button>
|
|
18
14
|
<button id="krypton-consent-all" style="border:0;background:#16a34a;color:#fff;padding:8px 12px;border-radius:8px;cursor:pointer">Accept all</button>
|
|
19
15
|
<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
16
|
</div>
|
|
21
|
-
`;let n=()=>{t.remove();try{document.body&&(document.body.style.cursor=""),document.documentElement&&(document.documentElement.style.cursor="")}catch{}},i=a=>!!document.getElementById(a)?.checked;t.querySelector("#krypton-consent-save")?.addEventListener("click",()=>{let a={analytics:i("krypton-consent-analytics"),heatmaps:i("krypton-consent-heatmaps")
|
|
17
|
+
`;let n=()=>{t.remove();try{document.body&&(document.body.style.cursor=""),document.documentElement&&(document.documentElement.style.cursor="")}catch{}},i=a=>!!document.getElementById(a)?.checked;t.querySelector("#krypton-consent-save")?.addEventListener("click",()=>{let a={analytics:i("krypton-consent-analytics"),heatmaps:i("krypton-consent-heatmaps")};n(),setTimeout(()=>this.setConsent(a),0)}),t.querySelector("#krypton-consent-all")?.addEventListener("click",()=>{n(),setTimeout(()=>this.setConsent({analytics:!0,heatmaps:!0}),0)}),t.querySelector("#krypton-consent-none")?.addEventListener("click",()=>{n(),setTimeout(()=>this.setConsent({analytics:!1,heatmaps:!1}),0)}),document.body.appendChild(t)}setConsent(t,r=!0){try{let n={...this.consent};this.consent={analytics:t.analytics??n.analytics,heatmaps:t.heatmaps??n.heatmaps},r&&this.persistConsent(),!n.analytics&&this.consent.analytics&&(this.promotePersistentIds(),this.config.autoPageview&&this.trackPageview()),n.analytics&&!this.consent.analytics&&(this.eventQueue=[]),!n.heatmaps&&this.isHeatmapFeatureEnabled()&&(this.setupHeatmap(),this.captureSnapshot()),n.heatmaps&&!this.consent.heatmaps&&(this.heatmapQueue=[])}catch(n){this.warn("setConsent failed",n)}}getConsent(){return{...this.consent}}grantConsent(){this.setConsent({analytics:!0,heatmaps:!0})}revokeConsent(){this.setConsent({analytics:!1,heatmaps:!1}),this.eventQueue=[],this.heatmapQueue=[]}identify(t){try{if(this.distinctId=t,this.canTrackAnalytics())try{typeof localStorage<"u"&&localStorage.setItem("_krypton_did",t)}catch{}}catch(r){this.warn("identify failed",r)}}trackPageview(t){try{if(!this.canTrackAnalytics())return;this.track("$pageview",{...t})}catch(r){this.warn("trackPageview failed",r)}}track(t,r){try{if(!this.canTrackAnalytics())return;let n=me(),i={...r||{}},a={project_id:this.config.apiKey,distinct_id:this.distinctId,event_name:t,timestamp:new Date().toISOString(),properties:i,page_url:typeof window<"u"?window.location.href:"",page_title:typeof document<"u"?document.title:"",referrer:typeof document<"u"?document.referrer:"",utm_source:n.utm_source||"",utm_medium:n.utm_medium||"",utm_campaign:n.utm_campaign||"",utm_term:n.utm_term||"",utm_content:n.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()}catch(n){this.warn("track failed",n)}}async flush(){try{await Promise.all([this.flushEvents(),this.flushHeatmapEvents()])}catch(t){this.warn("flush failed",t)}}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};await this.safePost(`${this.config.endpoint}/api/v1/ingest/batch`,r)||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};await this.safePost(`${this.config.endpoint}/api/v1/heatmap`,r)||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 n=JSON.stringify(r),i={api_key:this.config.apiKey,page_url:t,snapshot:n,viewport_width:window.innerWidth,viewport_height:window.innerHeight,page_width:document.documentElement.scrollWidth,page_height:document.documentElement.scrollHeight,timestamp:new Date().toISOString()};this.safePost(`${this.config.endpoint}/api/v1/snapshot`,i)}catch{}},1e3))}setupHeatmap(){if(typeof window>"u"||this.heatmapSetup)return;this.heatmapSetup=!0,this.captureSnapshot(),document.addEventListener("click",n=>{if(this.isHeatmapFeatureEnabled())try{let i=n.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:n.clientX+window.scrollX,y:n.clientY+window.scrollY,viewport_width:window.innerWidth,viewport_height:window.innerHeight,page_width:document.documentElement.scrollWidth,page_height:document.documentElement.scrollHeight,selector:ve(i)})}catch(i){this.warn("heatmap click capture failed",i)}});let t=0,r=null;window.addEventListener("scroll",()=>{if(this.isHeatmapFeatureEnabled())try{let n=window.scrollY||document.documentElement.scrollTop,i=document.documentElement.scrollHeight-window.innerHeight,a=i>0?n/i*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)}catch(n){this.warn("heatmap scroll capture failed",n)}})}async safePost(t,r){try{let n=await fetch(t,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(r),keepalive:!0});return n.ok?!0:(this.warn(`API request failed (${n.status})`,{url:t}),!1)}catch(n){return this.warn("API request failed",{url:t,err:n}),!1}}warn(t,r){try{console.warn(`${this.logPrefix} ${t}`,r??"")}catch{}}debug(t,r){if(this.config.debug)try{console.log(`${this.logPrefix} ${t}`,r??"")}catch{}}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 we={Krypton:q,init:ye};typeof window<"u"&&(window.KryptonAnalytics=we);var it=we;return Ie(at);})();
|
package/dist/index.d.mts
CHANGED
|
@@ -17,12 +17,15 @@ interface KryptonConfig {
|
|
|
17
17
|
flushInterval?: number;
|
|
18
18
|
/** Max events per batch (default: 20) */
|
|
19
19
|
batchSize?: number;
|
|
20
|
+
/** Enable verbose SDK debug logs (default: false) */
|
|
21
|
+
debug?: boolean;
|
|
22
|
+
/** Disable SDK config cache and fetch project config on each init (default: false) */
|
|
23
|
+
disableConfigCache?: boolean;
|
|
20
24
|
}
|
|
21
|
-
type ConsentCategory = "analytics" | "heatmaps"
|
|
25
|
+
type ConsentCategory = "analytics" | "heatmaps";
|
|
22
26
|
interface ConsentPreferences {
|
|
23
27
|
analytics: boolean;
|
|
24
28
|
heatmaps: boolean;
|
|
25
|
-
geo: boolean;
|
|
26
29
|
}
|
|
27
30
|
interface EventPayload {
|
|
28
31
|
project_id: string;
|
|
@@ -74,8 +77,6 @@ declare class Krypton {
|
|
|
74
77
|
private initialized;
|
|
75
78
|
private lastSnapshotUrl;
|
|
76
79
|
private heatmapSetup;
|
|
77
|
-
private geoRequested;
|
|
78
|
-
private geoContext;
|
|
79
80
|
private consent;
|
|
80
81
|
private serverConfig;
|
|
81
82
|
private configFetched;
|
|
@@ -93,7 +94,7 @@ declare class Krypton {
|
|
|
93
94
|
private isHeatmapFeatureEnabled;
|
|
94
95
|
private fetchConfig;
|
|
95
96
|
private setupTracking;
|
|
96
|
-
/** Built-in consent popup with category toggles (analytics, heatmaps
|
|
97
|
+
/** Built-in consent popup with category toggles (analytics, heatmaps). */
|
|
97
98
|
showConsentBanner(): void;
|
|
98
99
|
/** Set one or more consent categories and apply changes immediately. */
|
|
99
100
|
setConsent(next: Partial<ConsentPreferences>, persist?: boolean): void;
|
|
@@ -110,13 +111,13 @@ declare class Krypton {
|
|
|
110
111
|
track(eventName: string, properties?: Record<string, unknown>): void;
|
|
111
112
|
flush(): Promise<void>;
|
|
112
113
|
shutdown(): void;
|
|
113
|
-
private captureGeoOnce;
|
|
114
114
|
private flushEvents;
|
|
115
115
|
private flushHeatmapEvents;
|
|
116
116
|
private captureSnapshot;
|
|
117
117
|
private setupHeatmap;
|
|
118
118
|
private safePost;
|
|
119
119
|
private warn;
|
|
120
|
+
private debug;
|
|
120
121
|
private getBrowser;
|
|
121
122
|
}
|
|
122
123
|
declare function createKrypton(config: KryptonConfig): Krypton;
|
package/dist/index.d.ts
CHANGED
|
@@ -17,12 +17,15 @@ interface KryptonConfig {
|
|
|
17
17
|
flushInterval?: number;
|
|
18
18
|
/** Max events per batch (default: 20) */
|
|
19
19
|
batchSize?: number;
|
|
20
|
+
/** Enable verbose SDK debug logs (default: false) */
|
|
21
|
+
debug?: boolean;
|
|
22
|
+
/** Disable SDK config cache and fetch project config on each init (default: false) */
|
|
23
|
+
disableConfigCache?: boolean;
|
|
20
24
|
}
|
|
21
|
-
type ConsentCategory = "analytics" | "heatmaps"
|
|
25
|
+
type ConsentCategory = "analytics" | "heatmaps";
|
|
22
26
|
interface ConsentPreferences {
|
|
23
27
|
analytics: boolean;
|
|
24
28
|
heatmaps: boolean;
|
|
25
|
-
geo: boolean;
|
|
26
29
|
}
|
|
27
30
|
interface EventPayload {
|
|
28
31
|
project_id: string;
|
|
@@ -74,8 +77,6 @@ declare class Krypton {
|
|
|
74
77
|
private initialized;
|
|
75
78
|
private lastSnapshotUrl;
|
|
76
79
|
private heatmapSetup;
|
|
77
|
-
private geoRequested;
|
|
78
|
-
private geoContext;
|
|
79
80
|
private consent;
|
|
80
81
|
private serverConfig;
|
|
81
82
|
private configFetched;
|
|
@@ -93,7 +94,7 @@ declare class Krypton {
|
|
|
93
94
|
private isHeatmapFeatureEnabled;
|
|
94
95
|
private fetchConfig;
|
|
95
96
|
private setupTracking;
|
|
96
|
-
/** Built-in consent popup with category toggles (analytics, heatmaps
|
|
97
|
+
/** Built-in consent popup with category toggles (analytics, heatmaps). */
|
|
97
98
|
showConsentBanner(): void;
|
|
98
99
|
/** Set one or more consent categories and apply changes immediately. */
|
|
99
100
|
setConsent(next: Partial<ConsentPreferences>, persist?: boolean): void;
|
|
@@ -110,13 +111,13 @@ declare class Krypton {
|
|
|
110
111
|
track(eventName: string, properties?: Record<string, unknown>): void;
|
|
111
112
|
flush(): Promise<void>;
|
|
112
113
|
shutdown(): void;
|
|
113
|
-
private captureGeoOnce;
|
|
114
114
|
private flushEvents;
|
|
115
115
|
private flushHeatmapEvents;
|
|
116
116
|
private captureSnapshot;
|
|
117
117
|
private setupHeatmap;
|
|
118
118
|
private safePost;
|
|
119
119
|
private warn;
|
|
120
|
+
private debug;
|
|
120
121
|
private getBrowser;
|
|
121
122
|
}
|
|
122
123
|
declare function createKrypton(config: KryptonConfig): Krypton;
|
package/dist/index.js
CHANGED
|
@@ -113,8 +113,6 @@ var Krypton = class {
|
|
|
113
113
|
this.initialized = false;
|
|
114
114
|
this.lastSnapshotUrl = null;
|
|
115
115
|
this.heatmapSetup = false;
|
|
116
|
-
this.geoRequested = false;
|
|
117
|
-
this.geoContext = null;
|
|
118
116
|
this.serverConfig = null;
|
|
119
117
|
this.configFetched = false;
|
|
120
118
|
this.logPrefix = "[Krypton SDK]";
|
|
@@ -126,6 +124,8 @@ var Krypton = class {
|
|
|
126
124
|
consentCategories: {},
|
|
127
125
|
flushInterval: 5e3,
|
|
128
126
|
batchSize: 20,
|
|
127
|
+
debug: false,
|
|
128
|
+
disableConfigCache: false,
|
|
129
129
|
...config
|
|
130
130
|
};
|
|
131
131
|
this.distinctId = generateId();
|
|
@@ -147,7 +147,17 @@ var Krypton = class {
|
|
|
147
147
|
}
|
|
148
148
|
try {
|
|
149
149
|
if (this.config.consentRequired && this.config.showConsentBanner && !this.hasStoredConsent()) {
|
|
150
|
+
this.debug("showing consent banner automatically", {
|
|
151
|
+
consentRequired: this.config.consentRequired,
|
|
152
|
+
showConsentBanner: this.config.showConsentBanner
|
|
153
|
+
});
|
|
150
154
|
this.showConsentBannerWhenReady();
|
|
155
|
+
} else {
|
|
156
|
+
this.debug("skipping consent banner", {
|
|
157
|
+
consentRequired: this.config.consentRequired,
|
|
158
|
+
showConsentBanner: this.config.showConsentBanner,
|
|
159
|
+
hasStoredConsent: this.hasStoredConsent()
|
|
160
|
+
});
|
|
151
161
|
}
|
|
152
162
|
} catch (err) {
|
|
153
163
|
this.warn("consent banner initialization failed", err);
|
|
@@ -167,10 +177,9 @@ var Krypton = class {
|
|
|
167
177
|
resolveInitialConsent() {
|
|
168
178
|
const stored = this.loadStoredConsent();
|
|
169
179
|
if (stored) return stored;
|
|
170
|
-
const base = this.config.consentRequired ? { analytics: false, heatmaps: false
|
|
180
|
+
const base = this.config.consentRequired ? { analytics: false, heatmaps: false } : {
|
|
171
181
|
analytics: true,
|
|
172
|
-
heatmaps: !!this.config.heatmap
|
|
173
|
-
geo: false
|
|
182
|
+
heatmaps: !!this.config.heatmap
|
|
174
183
|
};
|
|
175
184
|
return {
|
|
176
185
|
...base,
|
|
@@ -196,8 +205,7 @@ var Krypton = class {
|
|
|
196
205
|
const parsed = JSON.parse(raw);
|
|
197
206
|
return {
|
|
198
207
|
analytics: !!parsed.analytics,
|
|
199
|
-
heatmaps: !!parsed.heatmaps
|
|
200
|
-
geo: !!parsed.geo
|
|
208
|
+
heatmaps: !!parsed.heatmaps
|
|
201
209
|
};
|
|
202
210
|
} catch {
|
|
203
211
|
return null;
|
|
@@ -226,10 +234,12 @@ var Krypton = class {
|
|
|
226
234
|
if (typeof window === "undefined") return;
|
|
227
235
|
const cacheKey = `_krypton_config_${this.config.apiKey}`;
|
|
228
236
|
let cached = null;
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
237
|
+
if (!this.config.disableConfigCache) {
|
|
238
|
+
try {
|
|
239
|
+
cached = sessionStorage.getItem(cacheKey);
|
|
240
|
+
} catch {
|
|
241
|
+
cached = null;
|
|
242
|
+
}
|
|
233
243
|
}
|
|
234
244
|
if (cached) {
|
|
235
245
|
try {
|
|
@@ -237,6 +247,7 @@ var Krypton = class {
|
|
|
237
247
|
if (parsed._ts && Date.now() - parsed._ts < 5 * 60 * 1e3) {
|
|
238
248
|
this.serverConfig = parsed;
|
|
239
249
|
this.configFetched = true;
|
|
250
|
+
this.debug("config loaded from session cache", parsed);
|
|
240
251
|
return;
|
|
241
252
|
}
|
|
242
253
|
} catch {
|
|
@@ -254,12 +265,18 @@ var Krypton = class {
|
|
|
254
265
|
const data = await res.json();
|
|
255
266
|
this.serverConfig = data;
|
|
256
267
|
this.configFetched = true;
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
268
|
+
this.debug("config fetched from API", data);
|
|
269
|
+
if (!this.config.disableConfigCache) {
|
|
270
|
+
try {
|
|
271
|
+
sessionStorage.setItem(cacheKey, JSON.stringify({ ...data, _ts: Date.now() }));
|
|
272
|
+
} catch {
|
|
273
|
+
}
|
|
260
274
|
}
|
|
275
|
+
} else {
|
|
276
|
+
this.warn(`Config fetch failed (${res.status})`, { endpoint: this.config.endpoint });
|
|
261
277
|
}
|
|
262
|
-
} catch {
|
|
278
|
+
} catch (err) {
|
|
279
|
+
this.warn("Config fetch failed", err);
|
|
263
280
|
}
|
|
264
281
|
}
|
|
265
282
|
setupTracking() {
|
|
@@ -316,11 +333,8 @@ var Krypton = class {
|
|
|
316
333
|
if (this.isHeatmapFeatureEnabled()) {
|
|
317
334
|
this.setupHeatmap();
|
|
318
335
|
}
|
|
319
|
-
if (this.consent.geo) {
|
|
320
|
-
this.captureGeoOnce();
|
|
321
|
-
}
|
|
322
336
|
}
|
|
323
|
-
/** Built-in consent popup with category toggles (analytics, heatmaps
|
|
337
|
+
/** Built-in consent popup with category toggles (analytics, heatmaps). */
|
|
324
338
|
showConsentBanner() {
|
|
325
339
|
if (typeof document === "undefined") return;
|
|
326
340
|
if (document.getElementById("krypton-consent-banner")) return;
|
|
@@ -355,11 +369,7 @@ var Krypton = class {
|
|
|
355
369
|
<input type="checkbox" id="krypton-consent-heatmaps" ${checked(this.consent.heatmaps)} />
|
|
356
370
|
<span><strong>Heatmaps</strong> (click and scroll interaction maps)</span>
|
|
357
371
|
</label>
|
|
358
|
-
<
|
|
359
|
-
<input type="checkbox" id="krypton-consent-geo" ${checked(this.consent.geo)} />
|
|
360
|
-
<span><strong>Geo location</strong> (browser geolocation if available)</span>
|
|
361
|
-
</label>
|
|
362
|
-
<div style="display:flex;gap:8px;flex-wrap:wrap">
|
|
372
|
+
<div style="display:flex;gap:8px;flex-wrap:wrap;margin-top:12px">
|
|
363
373
|
<button id="krypton-consent-save" style="border:0;background:#2563eb;color:#fff;padding:8px 12px;border-radius:8px;cursor:pointer">Accept selected</button>
|
|
364
374
|
<button id="krypton-consent-all" style="border:0;background:#16a34a;color:#fff;padding:8px 12px;border-radius:8px;cursor:pointer">Accept all</button>
|
|
365
375
|
<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>
|
|
@@ -380,19 +390,18 @@ var Krypton = class {
|
|
|
380
390
|
banner.querySelector("#krypton-consent-save")?.addEventListener("click", () => {
|
|
381
391
|
const next = {
|
|
382
392
|
analytics: readValue("krypton-consent-analytics"),
|
|
383
|
-
heatmaps: readValue("krypton-consent-heatmaps")
|
|
384
|
-
geo: readValue("krypton-consent-geo")
|
|
393
|
+
heatmaps: readValue("krypton-consent-heatmaps")
|
|
385
394
|
};
|
|
386
395
|
remove();
|
|
387
396
|
setTimeout(() => this.setConsent(next), 0);
|
|
388
397
|
});
|
|
389
398
|
banner.querySelector("#krypton-consent-all")?.addEventListener("click", () => {
|
|
390
399
|
remove();
|
|
391
|
-
setTimeout(() => this.setConsent({ analytics: true, heatmaps: true
|
|
400
|
+
setTimeout(() => this.setConsent({ analytics: true, heatmaps: true }), 0);
|
|
392
401
|
});
|
|
393
402
|
banner.querySelector("#krypton-consent-none")?.addEventListener("click", () => {
|
|
394
403
|
remove();
|
|
395
|
-
setTimeout(() => this.setConsent({ analytics: false, heatmaps: false
|
|
404
|
+
setTimeout(() => this.setConsent({ analytics: false, heatmaps: false }), 0);
|
|
396
405
|
});
|
|
397
406
|
document.body.appendChild(banner);
|
|
398
407
|
}
|
|
@@ -402,8 +411,7 @@ var Krypton = class {
|
|
|
402
411
|
const prev = { ...this.consent };
|
|
403
412
|
this.consent = {
|
|
404
413
|
analytics: next.analytics ?? prev.analytics,
|
|
405
|
-
heatmaps: next.heatmaps ?? prev.heatmaps
|
|
406
|
-
geo: next.geo ?? prev.geo
|
|
414
|
+
heatmaps: next.heatmaps ?? prev.heatmaps
|
|
407
415
|
};
|
|
408
416
|
if (persist) {
|
|
409
417
|
this.persistConsent();
|
|
@@ -424,9 +432,6 @@ var Krypton = class {
|
|
|
424
432
|
if (prev.heatmaps && !this.consent.heatmaps) {
|
|
425
433
|
this.heatmapQueue = [];
|
|
426
434
|
}
|
|
427
|
-
if (!prev.geo && this.consent.geo) {
|
|
428
|
-
this.captureGeoOnce();
|
|
429
|
-
}
|
|
430
435
|
} catch (err) {
|
|
431
436
|
this.warn("setConsent failed", err);
|
|
432
437
|
}
|
|
@@ -436,11 +441,11 @@ var Krypton = class {
|
|
|
436
441
|
}
|
|
437
442
|
/** Backward-compatible: grant all categories. */
|
|
438
443
|
grantConsent() {
|
|
439
|
-
this.setConsent({ analytics: true, heatmaps: true
|
|
444
|
+
this.setConsent({ analytics: true, heatmaps: true });
|
|
440
445
|
}
|
|
441
446
|
/** Backward-compatible: revoke all categories and clear queues. */
|
|
442
447
|
revokeConsent() {
|
|
443
|
-
this.setConsent({ analytics: false, heatmaps: false
|
|
448
|
+
this.setConsent({ analytics: false, heatmaps: false });
|
|
444
449
|
this.eventQueue = [];
|
|
445
450
|
this.heatmapQueue = [];
|
|
446
451
|
}
|
|
@@ -477,9 +482,6 @@ var Krypton = class {
|
|
|
477
482
|
if (!this.canTrackAnalytics()) return;
|
|
478
483
|
const utm = getUTMParams();
|
|
479
484
|
const mergedProperties = { ...properties || {} };
|
|
480
|
-
if (this.consent.geo && this.geoContext) {
|
|
481
|
-
mergedProperties.geo = this.geoContext;
|
|
482
|
-
}
|
|
483
485
|
const event = {
|
|
484
486
|
project_id: this.config.apiKey,
|
|
485
487
|
distinct_id: this.distinctId,
|
|
@@ -522,30 +524,6 @@ var Krypton = class {
|
|
|
522
524
|
}
|
|
523
525
|
void this.flush();
|
|
524
526
|
}
|
|
525
|
-
captureGeoOnce() {
|
|
526
|
-
if (this.geoRequested) return;
|
|
527
|
-
if (!this.consent.geo) return;
|
|
528
|
-
if (typeof navigator === "undefined" || !navigator.geolocation) return;
|
|
529
|
-
this.geoRequested = true;
|
|
530
|
-
navigator.geolocation.getCurrentPosition(
|
|
531
|
-
(pos) => {
|
|
532
|
-
const round = (value, precision = 3) => Number(value.toFixed(precision));
|
|
533
|
-
this.geoContext = {
|
|
534
|
-
lat: round(pos.coords.latitude),
|
|
535
|
-
lon: round(pos.coords.longitude),
|
|
536
|
-
accuracy_m: Math.round(pos.coords.accuracy),
|
|
537
|
-
captured_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
538
|
-
};
|
|
539
|
-
},
|
|
540
|
-
() => {
|
|
541
|
-
},
|
|
542
|
-
{
|
|
543
|
-
enableHighAccuracy: false,
|
|
544
|
-
maximumAge: 10 * 60 * 1e3,
|
|
545
|
-
timeout: 5e3
|
|
546
|
-
}
|
|
547
|
-
);
|
|
548
|
-
}
|
|
549
527
|
async flushEvents() {
|
|
550
528
|
if (this.eventQueue.length === 0) return;
|
|
551
529
|
const events = this.eventQueue.splice(0, this.eventQueue.length);
|
|
@@ -688,6 +666,13 @@ var Krypton = class {
|
|
|
688
666
|
} catch {
|
|
689
667
|
}
|
|
690
668
|
}
|
|
669
|
+
debug(message, details) {
|
|
670
|
+
if (!this.config.debug) return;
|
|
671
|
+
try {
|
|
672
|
+
console.log(`${this.logPrefix} ${message}`, details ?? "");
|
|
673
|
+
} catch {
|
|
674
|
+
}
|
|
675
|
+
}
|
|
691
676
|
getBrowser() {
|
|
692
677
|
if (typeof navigator === "undefined") return "unknown";
|
|
693
678
|
const ua = navigator.userAgent;
|
package/dist/index.mjs
CHANGED
|
@@ -88,8 +88,6 @@ var Krypton = class {
|
|
|
88
88
|
this.initialized = false;
|
|
89
89
|
this.lastSnapshotUrl = null;
|
|
90
90
|
this.heatmapSetup = false;
|
|
91
|
-
this.geoRequested = false;
|
|
92
|
-
this.geoContext = null;
|
|
93
91
|
this.serverConfig = null;
|
|
94
92
|
this.configFetched = false;
|
|
95
93
|
this.logPrefix = "[Krypton SDK]";
|
|
@@ -101,6 +99,8 @@ var Krypton = class {
|
|
|
101
99
|
consentCategories: {},
|
|
102
100
|
flushInterval: 5e3,
|
|
103
101
|
batchSize: 20,
|
|
102
|
+
debug: false,
|
|
103
|
+
disableConfigCache: false,
|
|
104
104
|
...config
|
|
105
105
|
};
|
|
106
106
|
this.distinctId = generateId();
|
|
@@ -122,7 +122,17 @@ var Krypton = class {
|
|
|
122
122
|
}
|
|
123
123
|
try {
|
|
124
124
|
if (this.config.consentRequired && this.config.showConsentBanner && !this.hasStoredConsent()) {
|
|
125
|
+
this.debug("showing consent banner automatically", {
|
|
126
|
+
consentRequired: this.config.consentRequired,
|
|
127
|
+
showConsentBanner: this.config.showConsentBanner
|
|
128
|
+
});
|
|
125
129
|
this.showConsentBannerWhenReady();
|
|
130
|
+
} else {
|
|
131
|
+
this.debug("skipping consent banner", {
|
|
132
|
+
consentRequired: this.config.consentRequired,
|
|
133
|
+
showConsentBanner: this.config.showConsentBanner,
|
|
134
|
+
hasStoredConsent: this.hasStoredConsent()
|
|
135
|
+
});
|
|
126
136
|
}
|
|
127
137
|
} catch (err) {
|
|
128
138
|
this.warn("consent banner initialization failed", err);
|
|
@@ -142,10 +152,9 @@ var Krypton = class {
|
|
|
142
152
|
resolveInitialConsent() {
|
|
143
153
|
const stored = this.loadStoredConsent();
|
|
144
154
|
if (stored) return stored;
|
|
145
|
-
const base = this.config.consentRequired ? { analytics: false, heatmaps: false
|
|
155
|
+
const base = this.config.consentRequired ? { analytics: false, heatmaps: false } : {
|
|
146
156
|
analytics: true,
|
|
147
|
-
heatmaps: !!this.config.heatmap
|
|
148
|
-
geo: false
|
|
157
|
+
heatmaps: !!this.config.heatmap
|
|
149
158
|
};
|
|
150
159
|
return {
|
|
151
160
|
...base,
|
|
@@ -171,8 +180,7 @@ var Krypton = class {
|
|
|
171
180
|
const parsed = JSON.parse(raw);
|
|
172
181
|
return {
|
|
173
182
|
analytics: !!parsed.analytics,
|
|
174
|
-
heatmaps: !!parsed.heatmaps
|
|
175
|
-
geo: !!parsed.geo
|
|
183
|
+
heatmaps: !!parsed.heatmaps
|
|
176
184
|
};
|
|
177
185
|
} catch {
|
|
178
186
|
return null;
|
|
@@ -201,10 +209,12 @@ var Krypton = class {
|
|
|
201
209
|
if (typeof window === "undefined") return;
|
|
202
210
|
const cacheKey = `_krypton_config_${this.config.apiKey}`;
|
|
203
211
|
let cached = null;
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
212
|
+
if (!this.config.disableConfigCache) {
|
|
213
|
+
try {
|
|
214
|
+
cached = sessionStorage.getItem(cacheKey);
|
|
215
|
+
} catch {
|
|
216
|
+
cached = null;
|
|
217
|
+
}
|
|
208
218
|
}
|
|
209
219
|
if (cached) {
|
|
210
220
|
try {
|
|
@@ -212,6 +222,7 @@ var Krypton = class {
|
|
|
212
222
|
if (parsed._ts && Date.now() - parsed._ts < 5 * 60 * 1e3) {
|
|
213
223
|
this.serverConfig = parsed;
|
|
214
224
|
this.configFetched = true;
|
|
225
|
+
this.debug("config loaded from session cache", parsed);
|
|
215
226
|
return;
|
|
216
227
|
}
|
|
217
228
|
} catch {
|
|
@@ -229,12 +240,18 @@ var Krypton = class {
|
|
|
229
240
|
const data = await res.json();
|
|
230
241
|
this.serverConfig = data;
|
|
231
242
|
this.configFetched = true;
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
243
|
+
this.debug("config fetched from API", data);
|
|
244
|
+
if (!this.config.disableConfigCache) {
|
|
245
|
+
try {
|
|
246
|
+
sessionStorage.setItem(cacheKey, JSON.stringify({ ...data, _ts: Date.now() }));
|
|
247
|
+
} catch {
|
|
248
|
+
}
|
|
235
249
|
}
|
|
250
|
+
} else {
|
|
251
|
+
this.warn(`Config fetch failed (${res.status})`, { endpoint: this.config.endpoint });
|
|
236
252
|
}
|
|
237
|
-
} catch {
|
|
253
|
+
} catch (err) {
|
|
254
|
+
this.warn("Config fetch failed", err);
|
|
238
255
|
}
|
|
239
256
|
}
|
|
240
257
|
setupTracking() {
|
|
@@ -291,11 +308,8 @@ var Krypton = class {
|
|
|
291
308
|
if (this.isHeatmapFeatureEnabled()) {
|
|
292
309
|
this.setupHeatmap();
|
|
293
310
|
}
|
|
294
|
-
if (this.consent.geo) {
|
|
295
|
-
this.captureGeoOnce();
|
|
296
|
-
}
|
|
297
311
|
}
|
|
298
|
-
/** Built-in consent popup with category toggles (analytics, heatmaps
|
|
312
|
+
/** Built-in consent popup with category toggles (analytics, heatmaps). */
|
|
299
313
|
showConsentBanner() {
|
|
300
314
|
if (typeof document === "undefined") return;
|
|
301
315
|
if (document.getElementById("krypton-consent-banner")) return;
|
|
@@ -330,11 +344,7 @@ var Krypton = class {
|
|
|
330
344
|
<input type="checkbox" id="krypton-consent-heatmaps" ${checked(this.consent.heatmaps)} />
|
|
331
345
|
<span><strong>Heatmaps</strong> (click and scroll interaction maps)</span>
|
|
332
346
|
</label>
|
|
333
|
-
<
|
|
334
|
-
<input type="checkbox" id="krypton-consent-geo" ${checked(this.consent.geo)} />
|
|
335
|
-
<span><strong>Geo location</strong> (browser geolocation if available)</span>
|
|
336
|
-
</label>
|
|
337
|
-
<div style="display:flex;gap:8px;flex-wrap:wrap">
|
|
347
|
+
<div style="display:flex;gap:8px;flex-wrap:wrap;margin-top:12px">
|
|
338
348
|
<button id="krypton-consent-save" style="border:0;background:#2563eb;color:#fff;padding:8px 12px;border-radius:8px;cursor:pointer">Accept selected</button>
|
|
339
349
|
<button id="krypton-consent-all" style="border:0;background:#16a34a;color:#fff;padding:8px 12px;border-radius:8px;cursor:pointer">Accept all</button>
|
|
340
350
|
<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>
|
|
@@ -355,19 +365,18 @@ var Krypton = class {
|
|
|
355
365
|
banner.querySelector("#krypton-consent-save")?.addEventListener("click", () => {
|
|
356
366
|
const next = {
|
|
357
367
|
analytics: readValue("krypton-consent-analytics"),
|
|
358
|
-
heatmaps: readValue("krypton-consent-heatmaps")
|
|
359
|
-
geo: readValue("krypton-consent-geo")
|
|
368
|
+
heatmaps: readValue("krypton-consent-heatmaps")
|
|
360
369
|
};
|
|
361
370
|
remove();
|
|
362
371
|
setTimeout(() => this.setConsent(next), 0);
|
|
363
372
|
});
|
|
364
373
|
banner.querySelector("#krypton-consent-all")?.addEventListener("click", () => {
|
|
365
374
|
remove();
|
|
366
|
-
setTimeout(() => this.setConsent({ analytics: true, heatmaps: true
|
|
375
|
+
setTimeout(() => this.setConsent({ analytics: true, heatmaps: true }), 0);
|
|
367
376
|
});
|
|
368
377
|
banner.querySelector("#krypton-consent-none")?.addEventListener("click", () => {
|
|
369
378
|
remove();
|
|
370
|
-
setTimeout(() => this.setConsent({ analytics: false, heatmaps: false
|
|
379
|
+
setTimeout(() => this.setConsent({ analytics: false, heatmaps: false }), 0);
|
|
371
380
|
});
|
|
372
381
|
document.body.appendChild(banner);
|
|
373
382
|
}
|
|
@@ -377,8 +386,7 @@ var Krypton = class {
|
|
|
377
386
|
const prev = { ...this.consent };
|
|
378
387
|
this.consent = {
|
|
379
388
|
analytics: next.analytics ?? prev.analytics,
|
|
380
|
-
heatmaps: next.heatmaps ?? prev.heatmaps
|
|
381
|
-
geo: next.geo ?? prev.geo
|
|
389
|
+
heatmaps: next.heatmaps ?? prev.heatmaps
|
|
382
390
|
};
|
|
383
391
|
if (persist) {
|
|
384
392
|
this.persistConsent();
|
|
@@ -399,9 +407,6 @@ var Krypton = class {
|
|
|
399
407
|
if (prev.heatmaps && !this.consent.heatmaps) {
|
|
400
408
|
this.heatmapQueue = [];
|
|
401
409
|
}
|
|
402
|
-
if (!prev.geo && this.consent.geo) {
|
|
403
|
-
this.captureGeoOnce();
|
|
404
|
-
}
|
|
405
410
|
} catch (err) {
|
|
406
411
|
this.warn("setConsent failed", err);
|
|
407
412
|
}
|
|
@@ -411,11 +416,11 @@ var Krypton = class {
|
|
|
411
416
|
}
|
|
412
417
|
/** Backward-compatible: grant all categories. */
|
|
413
418
|
grantConsent() {
|
|
414
|
-
this.setConsent({ analytics: true, heatmaps: true
|
|
419
|
+
this.setConsent({ analytics: true, heatmaps: true });
|
|
415
420
|
}
|
|
416
421
|
/** Backward-compatible: revoke all categories and clear queues. */
|
|
417
422
|
revokeConsent() {
|
|
418
|
-
this.setConsent({ analytics: false, heatmaps: false
|
|
423
|
+
this.setConsent({ analytics: false, heatmaps: false });
|
|
419
424
|
this.eventQueue = [];
|
|
420
425
|
this.heatmapQueue = [];
|
|
421
426
|
}
|
|
@@ -452,9 +457,6 @@ var Krypton = class {
|
|
|
452
457
|
if (!this.canTrackAnalytics()) return;
|
|
453
458
|
const utm = getUTMParams();
|
|
454
459
|
const mergedProperties = { ...properties || {} };
|
|
455
|
-
if (this.consent.geo && this.geoContext) {
|
|
456
|
-
mergedProperties.geo = this.geoContext;
|
|
457
|
-
}
|
|
458
460
|
const event = {
|
|
459
461
|
project_id: this.config.apiKey,
|
|
460
462
|
distinct_id: this.distinctId,
|
|
@@ -497,30 +499,6 @@ var Krypton = class {
|
|
|
497
499
|
}
|
|
498
500
|
void this.flush();
|
|
499
501
|
}
|
|
500
|
-
captureGeoOnce() {
|
|
501
|
-
if (this.geoRequested) return;
|
|
502
|
-
if (!this.consent.geo) return;
|
|
503
|
-
if (typeof navigator === "undefined" || !navigator.geolocation) return;
|
|
504
|
-
this.geoRequested = true;
|
|
505
|
-
navigator.geolocation.getCurrentPosition(
|
|
506
|
-
(pos) => {
|
|
507
|
-
const round = (value, precision = 3) => Number(value.toFixed(precision));
|
|
508
|
-
this.geoContext = {
|
|
509
|
-
lat: round(pos.coords.latitude),
|
|
510
|
-
lon: round(pos.coords.longitude),
|
|
511
|
-
accuracy_m: Math.round(pos.coords.accuracy),
|
|
512
|
-
captured_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
513
|
-
};
|
|
514
|
-
},
|
|
515
|
-
() => {
|
|
516
|
-
},
|
|
517
|
-
{
|
|
518
|
-
enableHighAccuracy: false,
|
|
519
|
-
maximumAge: 10 * 60 * 1e3,
|
|
520
|
-
timeout: 5e3
|
|
521
|
-
}
|
|
522
|
-
);
|
|
523
|
-
}
|
|
524
502
|
async flushEvents() {
|
|
525
503
|
if (this.eventQueue.length === 0) return;
|
|
526
504
|
const events = this.eventQueue.splice(0, this.eventQueue.length);
|
|
@@ -663,6 +641,13 @@ var Krypton = class {
|
|
|
663
641
|
} catch {
|
|
664
642
|
}
|
|
665
643
|
}
|
|
644
|
+
debug(message, details) {
|
|
645
|
+
if (!this.config.debug) return;
|
|
646
|
+
try {
|
|
647
|
+
console.log(`${this.logPrefix} ${message}`, details ?? "");
|
|
648
|
+
} catch {
|
|
649
|
+
}
|
|
650
|
+
}
|
|
666
651
|
getBrowser() {
|
|
667
652
|
if (typeof navigator === "undefined") return "unknown";
|
|
668
653
|
const ua = navigator.userAgent;
|