You're Invited:Meet the Socket Team at RSAC and BSidesSF 2026, March 23–26.RSVP
Socket
Book a DemoSign in
Socket

@topsort/analytics.js

Package Overview
Dependencies
Maintainers
2
Versions
15
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@topsort/analytics.js - npm Package Compare versions

Comparing version
2.1.0
to
2.2.0
+11
-0
CHANGELOG.md

@@ -9,2 +9,13 @@ # Changelog

## Version 2.2.0 (2023-11-13)
### Added
- support passing `additionalAttribution`
### Refactor
- Stop publishing to codebuild/s3
- Update dependencies
## Version 2.1.0 (2023-08-30)

@@ -11,0 +22,0 @@

+2
-0

@@ -11,2 +11,3 @@ interface Placement {

entity?: Entity;
additionalAttribution?: Entity;
placement: Placement;

@@ -20,2 +21,3 @@ occurredAt: string;

entity?: Entity;
additionalAttribution?: Entity;
placement: Placement;

@@ -22,0 +24,0 @@ occurredAt: string;

@@ -18,1 +18,9 @@ export interface Store<T> {

}
export declare class BidStore {
private _key;
private _storage;
private _bid;
constructor(key: string);
get(): string | undefined;
set(bid: string): void;
}
+1
-1

@@ -1,1 +0,1 @@

(function(d){typeof define=="function"&&define.amd?define(d):d()})(function(){"use strict";class d{constructor(){this._data=[]}get(){return this._data}set(e){this._data=e}}class m{constructor(e){this._key=e,this._storage=window.localStorage}get(){const e=this._storage.getItem(this._key);return e?JSON.parse(e):[]}set(e){this._storage.setItem(this._key,JSON.stringify(e))}}const O="ts-t",M="ts-q",N=250,v=3,P=25,A=250,_=9,R=0;function L(t,e){return e>0?t+(Math.random()+Math.pow(2,e))*1e3:0}function U(){var e;const t=new m(O);try{const s="3";if(t.set([{x:s}]),((e=t.get()[0])==null?void 0:e.x)===s)return new m(M)}catch{}return new d}class C{constructor(e){this._store=U(),this._processing=new Set,this._scheduled=!1,this._processor=e}append(e,s){let n=this._store.get();n.push({e,r:0,p:s!=null&&s.highPriority?_:R}),n=n.slice(-N),this._setEntries(n)}async _processNow(e){if(!e.length)return;const s=[];for(let i=e.length-1;i>=0&&s.length<P;i--){const c=e[i],l=c==null?void 0:c.e;l&&!this._processing.has(l.id)&&L(l.t,c.r)<=Date.now()&&(s.push(l),this._processing.add(l.id))}if(!s.length){this._scheduleProcessing();return}let n={done:new Set,retry:new Set};try{n=await this._processor(s)}catch{for(const c of s)n.done.add(c.id)}const o=[];for(const i of this._processing)s.find(c=>c.id===i)||o.push(i);this._processing=new Set(o);const r=this._store.get(),g=[];for(const i of r)n.done.has(i.e.id)||(n.retry.has(i.e.id)?i.r<v&&(i.r+=1,g.push(i)):g.push(i));this._setEntries(g)}_setEntries(e){this._store.set(e),e.length&&(e.some(s=>s.p===_)||this._store instanceof d?this._processNow(e):this._scheduleProcessing())}_scheduleProcessing(){this._scheduled||(this._scheduled=!0,setTimeout(()=>{this._scheduled=!1,this._processNow(this._store.get())},A))}}const q="2.1.0";async function x(t,e){try{const s=(e.url||"https://api.topsort.com")+"/v2/events",n=await fetch(s,{method:"POST",headers:{"Content-Type":"application/json","X-UA":`ts.js/${q}`,Authorization:"Bearer "+e.token},body:JSON.stringify(t),keepalive:!0});return{ok:n.ok,retry:n.status===429||n.status>=500}}catch{return{ok:!1,retry:!0}}}const S=2500,H=.5;let a=new Set;function I(){var t,e;return((e=(t=window.URL).createObjectURL)==null?void 0:e.call(t,new Blob).split("/").pop())||Math.random()+""}let u;function w(){if(u)return u;const t=B();if(t)return u=t,t;const e=I();return E(e),e}function E(t){const e=window.TS.cookieName||"tsuid";u=t,document.cookie=e+"="+t+";max-age=31536000"}function D(){return u=void 0,document.cookie="tsuid=",w()}window.TS.setUserId=E,window.TS.getUserId=w,window.TS.resetUserId=D;function B(){var s;const t=window.TS.cookieName||"tsuid";return(s=new RegExp("(^|;)\\s*"+t+"\\s*=\\s*([^;]+)").exec(document.cookie))==null?void 0:s.pop()}function X(t){const e=t.type,s={path:t.page};let n;t.product&&(n={type:"product",id:t.product});const o=new Date(t.t).toISOString();switch(e){case"Click":return{clicks:[{resolvedBidId:t.bid,entity:n,placement:s,occurredAt:o,opaqueUserId:t.uid,id:t.id}]};case"Impression":return{impressions:[{resolvedBidId:t.bid,entity:n,placement:s,occurredAt:o,opaqueUserId:t.uid,id:t.id}]};case"Purchase":return{purchases:[{occurredAt:o,opaqueUserId:t.uid,items:(t.items||[]).map(r=>({productId:r.product,quantity:r.quantity,unitPrice:r.price})),id:t.id}]}}}async function j(t){const e={done:new Set,retry:new Set},s=[];for(const n of t)s.push(x(X(n),window.TS).then(o=>{(o.retry?e.retry:e.done).add(n.id)}).catch(()=>{e.done.add(n.id)}));return await Promise.all(s),e}const z=new C(j);function h(t,e){const s=J(t);if(a.has(s))return;if(a.add(s),a.size>S){const o=a.values();for(let r=0;r<a.size-S;--r)o.next();a=new Set(o)}z.append(t);const n=new CustomEvent("topsort",{bubbles:!0,detail:t});e.dispatchEvent(n)}function J(t){return[t.page,t.type,t.product,t.bid].join("-")}function Y(){const t=window.location,e=t.hash;return e[1]==="/"?e:t.pathname}function f(t,e){const s=e.dataset.tsProduct,n=e.dataset.tsResolvedBid,o={type:t,product:s,bid:n,t:Date.now(),page:Y(),id:I(),uid:w()};return t==="Purchase"&&(o.items=JSON.parse(e.dataset.tsItems||"[]")),o}function G(t){if(!(t.currentTarget instanceof HTMLElement))return;const e=t.currentTarget.closest(y);e&&e instanceof HTMLElement&&h(f("Click",e),e)}const p=window.IntersectionObserver?new IntersectionObserver(t=>{for(const e of t)if(e.isIntersecting){const s=e.target;s instanceof HTMLElement&&(h(f("Impression",s),s),p&&p.unobserve(s))}},{threshold:H}):void 0,y="[data-ts-product],[data-ts-action],[data-ts-items],[data-ts-resolved-bid]";function K(t){const e=t.querySelectorAll("[data-ts-clickable]");(e.length===0?[t]:e).forEach(n=>n.addEventListener("click",G))}function T(t){Z(t)?h(f("Purchase",t),t):(p?p.observe(t):h(f("Impression",t),t),K(t))}function b(t){const e=t.querySelectorAll(y);for(let s=0;s<e.length;s++){const n=e[s];n instanceof HTMLElement&&T(n)}}function Z(t){return t.dataset.tsAction==="purchase"}function W(t){for(const e of t)if(e.type==="childList"){const s=new Set;for(let n=0;n<e.addedNodes.length;n++){const o=e.addedNodes[n];if((o==null?void 0:o.nodeType)===Node.ELEMENT_NODE){const r=o.parentElement;r&&!s.has(r)&&s.add(r)}for(const r of s)b(r)}}else if(e.type==="attributes"){if(!(e.target instanceof HTMLElement))continue;T(e.target)}}function k(){var s,n;if((s=window.TS)!=null&&s.loaded)return;if(window.TS.loaded=!0,!((n=window.TS)!=null&&n.token)){console.error("Missing TS token");return}b(document);const t=window.MutationObserver||window.WebKitMutationObserver||window.MozMutationObserver;new t(W).observe(document,{attributes:!0,childList:!0,subtree:!0,attributeFilter:["data-ts-product","data-ts-action","data-ts-items","data-ts-resolved-bid"]})}/complete|interactive|loaded/.test(document.readyState)?k():window.addEventListener("DOMContentLoaded",k)});
(function(u){typeof define=="function"&&define.amd?define(u):u()})(function(){"use strict";class u{constructor(){this._data=[]}get(){return this._data}set(e){this._data=e}}class _{constructor(e){this._key=e,this._storage=window.localStorage}get(){const e=this._storage.getItem(this._key);return e?JSON.parse(e):[]}set(e){this._storage.setItem(this._key,JSON.stringify(e))}}class M{constructor(e){this._key=e,this._storage=window.sessionStorage,this._bid=void 0}get(){try{return this._storage.getItem(this._key)??void 0}catch{return this._bid}}set(e){this._bid=e;try{this._storage.setItem(this._key,e)}catch{}}}const P="ts-t",v="ts-q",N=250,A=3,R=25,C=250,m=9,L=0;function U(t,e){return e>0?t+(Math.random()+Math.pow(2,e))*1e3:0}function q(){var e;const t=new _(P);try{const s="3";if(t.set([{x:s}]),((e=t.get()[0])==null?void 0:e.x)===s)return new _(v)}catch{}return new u}class x{constructor(e){this._store=q(),this._processing=new Set,this._scheduled=!1,this._processor=e}append(e,s){let o=this._store.get();o.push({e,r:0,p:s!=null&&s.highPriority?m:L}),o=o.slice(-N),this._setEntries(o)}async _processNow(e){if(!e.length)return;const s=[];for(let i=e.length-1;i>=0&&s.length<R;i--){const c=e[i],h=c==null?void 0:c.e;h&&!this._processing.has(h.id)&&U(h.t,c.r)<=Date.now()&&(s.push(h),this._processing.add(h.id))}if(!s.length){this._scheduleProcessing();return}let o={done:new Set,retry:new Set};try{o=await this._processor(s)}catch{for(const c of s)o.done.add(c.id)}const n=[];for(const i of this._processing)s.find(c=>c.id===i)||n.push(i);this._processing=new Set(n);const r=this._store.get(),d=[];for(const i of r)o.done.has(i.e.id)||(o.retry.has(i.e.id)?i.r<A&&(i.r+=1,d.push(i)):d.push(i));this._setEntries(d)}_setEntries(e){this._store.set(e),e.length&&(e.some(s=>s.p===m)||this._store instanceof u?this._processNow(e):this._scheduleProcessing())}_scheduleProcessing(){this._scheduled||(this._scheduled=!0,setTimeout(()=>{this._scheduled=!1,this._processNow(this._store.get())},C))}}const H="2.2.0";async function B(t,e){try{const s=(e.url||"https://api.topsort.com")+"/v2/events",o=await fetch(s,{method:"POST",headers:{"Content-Type":"application/json","X-UA":`ts.js/${H}`,Authorization:"Bearer "+e.token},body:JSON.stringify(t),keepalive:!0});return{ok:o.ok,retry:o.status===429||o.status>=500}}catch{return{ok:!1,retry:!0}}}const S=2500,D=.5;let a=new Set;const I=new M("ts-b");function E(){var t,e;return((e=(t=window.URL).createObjectURL)==null?void 0:e.call(t,new Blob).split("/").pop())||Math.random()+""}let l;function g(){if(l)return l;const t=j();if(t)return l=t,t;const e=E();return y(e),e}function y(t){const e=window.TS.cookieName||"tsuid";l=t,document.cookie=e+"="+t+";max-age=31536000"}function X(){return l=void 0,document.cookie="tsuid=",g()}window.TS.setUserId=y,window.TS.getUserId=g,window.TS.resetUserId=X;function j(){var s;const t=window.TS.cookieName||"tsuid";return(s=new RegExp("(^|;)\\s*"+t+"\\s*=\\s*([^;]+)").exec(document.cookie))==null?void 0:s.pop()}function z(t){const e=t.type,s={path:t.page};let o;t.product&&(o={type:"product",id:t.product});let n;t.additionalProduct&&(n={type:"product",id:t.additionalProduct});const r=new Date(t.t).toISOString();switch(e){case"Click":return{clicks:[{resolvedBidId:t.bid,entity:o,additionalAttribution:n,placement:s,occurredAt:r,opaqueUserId:t.uid,id:t.id}]};case"Impression":return{impressions:[{resolvedBidId:t.bid,entity:o,additionalAttribution:n,placement:s,occurredAt:r,opaqueUserId:t.uid,id:t.id}]};case"Purchase":return{purchases:[{occurredAt:r,opaqueUserId:t.uid,items:(t.items||[]).map(d=>({productId:d.product,quantity:d.quantity,unitPrice:d.price})),id:t.id}]}}}async function J(t){const e={done:new Set,retry:new Set},s=[];for(const o of t)s.push(B(z(o),window.TS).then(n=>{(n.retry?e.retry:e.done).add(o.id)}).catch(()=>{e.done.add(o.id)}));return await Promise.all(s),e}const Y=new x(J);function f(t,e){const s=G(t);if(a.has(s))return;if(a.add(s),a.size>S){const n=a.values();for(let r=0;r<a.size-S;--r)n.next();a=new Set(n)}Y.append(t);const o=new CustomEvent("topsort",{bubbles:!0,detail:t});e.dispatchEvent(o)}function G(t){return[t.page,t.type,t.product??t.additionalProduct,t.bid].join("-")}function K(){const t=window.location,e=t.hash;return e[1]==="/"?e:t.pathname}function p(t,e){let s=e.dataset.tsProduct,o=e.dataset.tsResolvedBid,n;o=="inherit"&&s&&(t=="Click"||t=="Impression")&&(o=I.get(),n=s,s=void 0);const r={type:t,product:s,additionalProduct:n,bid:o,t:Date.now(),page:K(),id:E(),uid:g()};return t==="Purchase"&&(r.items=JSON.parse(e.dataset.tsItems||"[]")),r}function Z(t){if(!(t.currentTarget instanceof HTMLElement))return;const e=t.currentTarget.closest(b);if(e&&e instanceof HTMLElement){const s=p("Click",e);f(s,e),s.bid&&I.set(s.bid)}}const w=window.IntersectionObserver?new IntersectionObserver(t=>{for(const e of t)if(e.isIntersecting){const s=e.target;s instanceof HTMLElement&&(f(p("Impression",s),s),w&&w.unobserve(s))}},{threshold:D}):void 0,b="[data-ts-product],[data-ts-action],[data-ts-items],[data-ts-resolved-bid]";function W(t){const e=t.querySelectorAll("[data-ts-clickable]");(e.length===0?[t]:e).forEach(o=>o.addEventListener("click",Z))}function T(t){F(t)?f(p("Purchase",t),t):(w?w.observe(t):f(p("Impression",t),t),W(t))}function k(t){const e=t.querySelectorAll(b);for(let s=0;s<e.length;s++){const o=e[s];o instanceof HTMLElement&&T(o)}}function F(t){return t.dataset.tsAction==="purchase"}function Q(t){for(const e of t)if(e.type==="childList"){const s=new Set;for(let o=0;o<e.addedNodes.length;o++){const n=e.addedNodes[o];if((n==null?void 0:n.nodeType)===Node.ELEMENT_NODE){const r=n.parentElement;r&&!s.has(r)&&s.add(r)}for(const r of s)k(r)}}else if(e.type==="attributes"){if(!(e.target instanceof HTMLElement))continue;T(e.target)}}function O(){var s,o;if((s=window.TS)!=null&&s.loaded)return;if(window.TS.loaded=!0,!((o=window.TS)!=null&&o.token)){console.error("Missing TS token");return}k(document);const t=window.MutationObserver||window.WebKitMutationObserver||window.MozMutationObserver;new t(Q).observe(document,{attributes:!0,childList:!0,subtree:!0,attributeFilter:["data-ts-product","data-ts-action","data-ts-items","data-ts-resolved-bid"]})}/complete|interactive|loaded/.test(document.readyState)?O():window.addEventListener("DOMContentLoaded",O)});

@@ -24,13 +24,32 @@ class I {

}
const O = "ts-t", M = "ts-q", N = 250, v = 3, P = 25, A = 250, m = 9, R = 0;
function L(t, e) {
class M {
constructor(e) {
this._key = e, this._storage = window.sessionStorage, this._bid = void 0;
}
get() {
try {
return this._storage.getItem(this._key) ?? void 0;
} catch {
return this._bid;
}
}
set(e) {
this._bid = e;
try {
this._storage.setItem(this._key, e);
} catch {
}
}
}
const P = "ts-t", v = "ts-q", N = 250, A = 3, R = 25, C = 250, _ = 9, L = 0;
function U(t, e) {
return e > 0 ? t + (Math.random() + Math.pow(2, e)) * 1e3 : 0;
}
function U() {
function q() {
var e;
const t = new g(O);
const t = new g(P);
try {
const s = "3";
if (t.set([{ x: s }]), ((e = t.get()[0]) == null ? void 0 : e.x) === s)
return new g(M);
return new g(v);
} catch {

@@ -40,5 +59,5 @@ }

}
class C {
class x {
constructor(e) {
this._store = U(), this._processing = /* @__PURE__ */ new Set(), this._scheduled = !1, this._processor = e;
this._store = q(), this._processing = /* @__PURE__ */ new Set(), this._scheduled = !1, this._processor = e;
}

@@ -50,3 +69,3 @@ append(e, s) {

r: 0,
p: s != null && s.highPriority ? m : R
p: s != null && s.highPriority ? _ : L
}), o = o.slice(-N), this._setEntries(o);

@@ -58,5 +77,5 @@ }

const s = [];
for (let i = e.length - 1; i >= 0 && s.length < P; i--) {
const c = e[i], d = c == null ? void 0 : c.e;
d && !this._processing.has(d.id) && L(d.t, c.r) <= Date.now() && (s.push(d), this._processing.add(d.id));
for (let i = e.length - 1; i >= 0 && s.length < R; i--) {
const c = e[i], u = c == null ? void 0 : c.e;
u && !this._processing.has(u.id) && U(u.t, c.r) <= Date.now() && (s.push(u), this._processing.add(u.id));
}

@@ -74,13 +93,13 @@ if (!s.length) {

}
const n = [];
const r = [];
for (const i of this._processing)
s.find((c) => c.id === i) || n.push(i);
this._processing = new Set(n);
const r = this._store.get(), p = [];
for (const i of r)
o.done.has(i.e.id) || (o.retry.has(i.e.id) ? i.r < v && (i.r += 1, p.push(i)) : p.push(i));
this._setEntries(p);
s.find((c) => c.id === i) || r.push(i);
this._processing = new Set(r);
const n = this._store.get(), d = [];
for (const i of n)
o.done.has(i.e.id) || (o.retry.has(i.e.id) ? i.r < A && (i.r += 1, d.push(i)) : d.push(i));
this._setEntries(d);
}
_setEntries(e) {
this._store.set(e), e.length && (e.some((s) => s.p === m) || this._store instanceof I ? this._processNow(e) : this._scheduleProcessing());
this._store.set(e), e.length && (e.some((s) => s.p === _) || this._store instanceof I ? this._processNow(e) : this._scheduleProcessing());
}

@@ -90,7 +109,7 @@ _scheduleProcessing() {

this._scheduled = !1, this._processNow(this._store.get());
}, A));
}, C));
}
}
const q = "2.1.0";
async function x(t, e) {
const H = "2.2.0";
async function B(t, e) {
try {

@@ -103,3 +122,3 @@ const s = (e.url || "https://api.topsort.com") + "/v2/events", o = await fetch(s, {

// https://bugs.chromium.org/p/chromium/issues/detail?id=571722
"X-UA": `ts.js/${q}`,
"X-UA": `ts.js/${H}`,
Authorization: "Bearer " + e.token

@@ -116,29 +135,30 @@ },

}
const _ = 2500, H = 0.5;
const m = 2500, D = 0.5;
let a = /* @__PURE__ */ new Set();
function E() {
const E = new M("ts-b");
function y() {
var t, e;
return ((e = (t = window.URL).createObjectURL) == null ? void 0 : e.call(t, new Blob()).split("/").pop()) || Math.random() + "";
}
let u;
let l;
function w() {
if (u)
return u;
const t = B();
if (l)
return l;
const t = j();
if (t)
return u = t, t;
const e = E();
return y(e), e;
return l = t, t;
const e = y();
return b(e), e;
}
function y(t) {
function b(t) {
const e = window.TS.cookieName || "tsuid";
u = t, document.cookie = e + "=" + t + ";max-age=31536000";
l = t, document.cookie = e + "=" + t + ";max-age=31536000";
}
function D() {
return u = void 0, document.cookie = "tsuid=", w();
function X() {
return l = void 0, document.cookie = "tsuid=", w();
}
window.TS.setUserId = y;
window.TS.setUserId = b;
window.TS.getUserId = w;
window.TS.resetUserId = D;
function B() {
window.TS.resetUserId = X;
function j() {
var s;

@@ -148,3 +168,3 @@ const t = window.TS.cookieName || "tsuid";

}
function X(t) {
function z(t) {
const e = t.type, s = {

@@ -158,2 +178,7 @@ path: t.page

});
let r;
t.additionalProduct && (r = {
type: "product",
id: t.additionalProduct
});
const n = new Date(t.t).toISOString();

@@ -167,2 +192,3 @@ switch (e) {

entity: o,
additionalAttribution: r,
placement: s,

@@ -181,2 +207,3 @@ occurredAt: n,

entity: o,
additionalAttribution: r,
placement: s,

@@ -195,6 +222,6 @@ occurredAt: n,

opaqueUserId: t.uid,
items: (t.items || []).map((r) => ({
productId: r.product,
quantity: r.quantity,
unitPrice: r.price
items: (t.items || []).map((d) => ({
productId: d.product,
quantity: d.quantity,
unitPrice: d.price
})),

@@ -207,3 +234,3 @@ id: t.id

}
async function j(t) {
async function J(t) {
const e = {

@@ -215,4 +242,4 @@ done: /* @__PURE__ */ new Set(),

s.push(
x(X(o), window.TS).then((n) => {
(n.retry ? e.retry : e.done).add(o.id);
B(z(o), window.TS).then((r) => {
(r.retry ? e.retry : e.done).add(o.id);
}).catch(() => {

@@ -224,32 +251,40 @@ e.done.add(o.id);

}
const z = new C(j);
function l(t, e) {
const s = J(t);
const Y = new x(J);
function h(t, e) {
const s = G(t);
if (a.has(s))
return;
if (a.add(s), a.size > _) {
const n = a.values();
for (let r = 0; r < a.size - _; --r)
n.next();
a = new Set(n);
if (a.add(s), a.size > m) {
const r = a.values();
for (let n = 0; n < a.size - m; --n)
r.next();
a = new Set(r);
}
z.append(t);
Y.append(t);
const o = new CustomEvent("topsort", { bubbles: !0, detail: t });
e.dispatchEvent(o);
}
function J(t) {
return [t.page, t.type, t.product, t.bid].join("-");
function G(t) {
return [
t.page,
t.type,
t.product ?? t.additionalProduct,
t.bid
].join("-");
}
function Y() {
function K() {
const t = window.location, e = t.hash;
return e[1] === "/" ? e : t.pathname;
}
function h(t, e) {
const s = e.dataset.tsProduct, o = e.dataset.tsResolvedBid, n = {
function f(t, e) {
let s = e.dataset.tsProduct, o = e.dataset.tsResolvedBid, r;
o == "inherit" && s && (t == "Click" || t == "Impression") && (o = E.get(), r = s, s = void 0);
const n = {
type: t,
product: s,
additionalProduct: r,
bid: o,
t: Date.now(),
page: Y(),
id: E(),
page: K(),
id: y(),
uid: w()

@@ -259,9 +294,12 @@ };

}
function G(t) {
function Z(t) {
if (!(t.currentTarget instanceof HTMLElement))
return;
const e = t.currentTarget.closest(T);
e && e instanceof HTMLElement && l(h("Click", e), e);
if (e && e instanceof HTMLElement) {
const s = f("Click", e);
h(s, e), s.bid && E.set(s.bid);
}
}
const f = window.IntersectionObserver ? new IntersectionObserver(
const p = window.IntersectionObserver ? new IntersectionObserver(
(t) => {

@@ -271,27 +309,27 @@ for (const e of t)

const s = e.target;
s instanceof HTMLElement && (l(h("Impression", s), s), f && f.unobserve(s));
s instanceof HTMLElement && (h(f("Impression", s), s), p && p.unobserve(s));
}
},
{
threshold: H
threshold: D
}
) : void 0, T = "[data-ts-product],[data-ts-action],[data-ts-items],[data-ts-resolved-bid]";
function K(t) {
function W(t) {
const e = t.querySelectorAll("[data-ts-clickable]");
(e.length === 0 ? [t] : e).forEach((o) => o.addEventListener("click", G));
(e.length === 0 ? [t] : e).forEach((o) => o.addEventListener("click", Z));
}
function b(t) {
Z(t) ? l(h("Purchase", t), t) : (f ? f.observe(t) : l(h("Impression", t), t), K(t));
function k(t) {
F(t) ? h(f("Purchase", t), t) : (p ? p.observe(t) : h(f("Impression", t), t), W(t));
}
function k(t) {
function O(t) {
const e = t.querySelectorAll(T);
for (let s = 0; s < e.length; s++) {
const o = e[s];
o instanceof HTMLElement && b(o);
o instanceof HTMLElement && k(o);
}
}
function Z(t) {
function F(t) {
return t.dataset.tsAction === "purchase";
}
function W(t) {
function Q(t) {
for (const e of t)

@@ -301,9 +339,9 @@ if (e.type === "childList") {

for (let o = 0; o < e.addedNodes.length; o++) {
const n = e.addedNodes[o];
if ((n == null ? void 0 : n.nodeType) === Node.ELEMENT_NODE) {
const r = n.parentElement;
r && !s.has(r) && s.add(r);
const r = e.addedNodes[o];
if ((r == null ? void 0 : r.nodeType) === Node.ELEMENT_NODE) {
const n = r.parentElement;
n && !s.has(n) && s.add(n);
}
for (const r of s)
k(r);
for (const n of s)
O(n);
}

@@ -313,3 +351,3 @@ } else if (e.type === "attributes") {

continue;
b(e.target);
k(e.target);
}

@@ -325,5 +363,5 @@ }

}
k(document);
O(document);
const t = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;
new t(W).observe(document, {
new t(Q).observe(document, {
attributes: !0,

@@ -330,0 +368,0 @@ childList: !0,

{
"name": "@topsort/analytics.js",
"version": "2.1.0",
"version": "2.2.0",
"description": "JS library to automatically report events to Topsort's Analytics",

@@ -41,12 +41,12 @@ "main": "dist/ts.js",

"@types/express": "^4.17.17",
"@types/node": "^20.5.7",
"@types/node": "^20.8.10",
"@types/react": "^18.2.21",
"@types/react-dom": "^18.2.7",
"@types/react-dom": "^18.2.8",
"@typescript-eslint/eslint-plugin": "^6.5.0",
"@typescript-eslint/parser": "^6.5.0",
"@typescript-eslint/parser": "^6.9.1",
"@vitest/coverage-v8": "^0.34.3",
"eslint": "^8.48.0",
"eslint": "^8.52.0",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-prettier": "^5.0.0",
"eslint-plugin-vitest": "^0.2.8",
"eslint-plugin-vitest": "^0.3.1",
"express": "^4.18.2",

@@ -58,6 +58,6 @@ "jsdom": "^22.1.0",

"react-dom": "^18.2.0",
"react-router-dom": "^6.15.0",
"react-router-dom": "^6.16.0",
"tslib": "^2.6.2",
"typescript": "^5.2.2",
"vite": "^4.4.9",
"vite": "^4.5.0",
"vite-plugin-dts": "^3.5.3",

@@ -64,0 +64,0 @@ "vitest": "^0.33.0"

+22
-10

@@ -31,3 +31,3 @@ ![version](https://img.shields.io/npm/v/@topsort/analytics.js)

</script>
<script src="https://unpkg.com/@topsort/analytics.js@2.0.0/dist/ts.js"></script>
<script src="https://unpkg.com/@topsort/analytics.js@2.2.0/dist/ts.js"></script>
```

@@ -43,14 +43,14 @@

Pass said values to your html:
Add the following markup to promoted products:
```html
<div
class="product"
data-ts-product="<productId>"
data-ts-resolved-bid="<resolvedBidId>"
>
...
</div>
<div class="product" data-ts-resolved-bid="<resolvedBidId>">...</div>
```
and the following for organic products (which is optional)
```html
<div class="product" data-ts-product="<productId>">...</div>
```
Additionally, in case not all the container is clickable (i.e., does not produce an action or does not take you to the product page) or parts of it lead you to a non-related product page, make sure to use the `data-ts-clickable` attribute to indicate what portions of the product should count as a conversion.

@@ -68,3 +68,3 @@

Finally, adding further information to purchases can be made by passing the `ts-data-items` JSON array:
Adding further information to purchases can be made by passing the `ts-data-items` JSON array:

@@ -80,2 +80,14 @@ ```html

Finally, in case you are using banners and want to have further control on the attributable products you need to add the following markup in the banner's destination page.
```html
<div
class="product"
data-ts-product="<productId>"
data-ts-resolved-bid="inherit"
>
...
</div>
```
# E2E tests

@@ -82,0 +94,0 @@