@jmp-technologies/analytics 0.1.17 → 0.1.19
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 +3 -1
- package/dist/{chunk-3ELQETAA.js → chunk-EPNF76VK.js} +2 -2
- package/dist/{chunk-MUHLIN7P.js → chunk-GB37RVJJ.js} +339 -103
- package/dist/chunk-GB37RVJJ.js.map +1 -0
- package/dist/index.cjs +348 -104
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +112 -35
- package/dist/index.d.ts +112 -35
- package/dist/index.js +21 -5
- package/dist/next/content.cjs +322 -0
- package/dist/next/content.cjs.map +1 -0
- package/dist/next/content.d.cts +37 -0
- package/dist/next/content.d.ts +37 -0
- package/dist/next/content.js +172 -0
- package/dist/next/content.js.map +1 -0
- package/dist/next/instrumentation.cjs +131 -0
- package/dist/next/instrumentation.cjs.map +1 -0
- package/dist/next/instrumentation.d.cts +7 -0
- package/dist/next/instrumentation.d.ts +7 -0
- package/dist/next/instrumentation.js +18 -0
- package/dist/next/instrumentation.js.map +1 -0
- package/dist/next/middleware.cjs +147 -0
- package/dist/next/middleware.cjs.map +1 -0
- package/dist/next/middleware.d.cts +13 -0
- package/dist/next/middleware.d.ts +13 -0
- package/dist/next/middleware.js +22 -0
- package/dist/next/middleware.js.map +1 -0
- package/dist/next.cjs +322 -86
- package/dist/next.cjs.map +1 -1
- package/dist/next.d.cts +24 -8
- package/dist/next.d.ts +24 -8
- package/dist/next.js +41 -13
- package/dist/next.js.map +1 -1
- package/dist/react.cjs +279 -69
- package/dist/react.cjs.map +1 -1
- package/dist/react.js +2 -2
- package/docs/legal-and-privacy.md +1 -0
- package/package.json +17 -2
- package/dist/chunk-MUHLIN7P.js.map +0 -1
- /package/dist/{chunk-3ELQETAA.js.map → chunk-EPNF76VK.js.map} +0 -0
package/dist/index.cjs
CHANGED
|
@@ -20,25 +20,33 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
+
BOOKING_LINK_HOSTS: () => BOOKING_LINK_HOSTS,
|
|
23
24
|
DEFAULT_JMP_BROWSER_PAGE_VIEW_DEDUPE_MS: () => DEFAULT_JMP_BROWSER_PAGE_VIEW_DEDUPE_MS,
|
|
25
|
+
JMP_ANALYTICS_SDK_VERSION: () => JMP_ANALYTICS_SDK_VERSION,
|
|
26
|
+
JMP_TRACKING_CONSENT_STORAGE_KEY: () => JMP_TRACKING_CONSENT_STORAGE_KEY,
|
|
24
27
|
buildLandingCaptureInlineScript: () => buildLandingCaptureInlineScript,
|
|
28
|
+
classifyContactHref: () => classifyContactHref,
|
|
25
29
|
createJmpAnalytics: () => createJmpAnalytics,
|
|
26
30
|
createJmpContentClient: () => createJmpContentClient,
|
|
27
31
|
createJmpContentClientFromServerEnv: () => createJmpContentClientFromServerEnv,
|
|
32
|
+
defineJmpSite: () => defineJmpSite,
|
|
28
33
|
getJmpBlogPost: () => getJmpBlogPost,
|
|
29
34
|
getJmpBlogPosts: () => getJmpBlogPosts,
|
|
30
35
|
getJmpBrowserAnalyticsConfigFromEnv: () => getJmpBrowserAnalyticsConfigFromEnv,
|
|
36
|
+
getJmpContentConfig: () => getJmpContentConfig,
|
|
31
37
|
getJmpFaqs: () => getJmpFaqs,
|
|
32
38
|
getJmpRobotsTxt: () => getJmpRobotsTxt,
|
|
33
39
|
getJmpServerContentConfigFromEnv: () => getJmpServerContentConfigFromEnv,
|
|
40
|
+
getJmpSiteDefinition: () => getJmpSiteDefinition,
|
|
34
41
|
getJmpSiteProfile: () => getJmpSiteProfile,
|
|
35
42
|
getJmpTrustBundle: () => getJmpTrustBundle,
|
|
36
43
|
getOrCreateJmpAnalyticsFromBrowserEnv: () => getOrCreateJmpAnalyticsFromBrowserEnv,
|
|
37
44
|
isJmpBrowserAnalyticsEnvConfigured: () => isJmpBrowserAnalyticsEnvConfigured,
|
|
38
45
|
isJmpServerContentEnvConfigured: () => isJmpServerContentEnvConfigured,
|
|
46
|
+
isJmpTrackingConsentGranted: () => isJmpTrackingConsentGranted,
|
|
39
47
|
registerJmpContentWrappers: () => registerJmpContentWrappers,
|
|
40
|
-
|
|
41
|
-
|
|
48
|
+
setJmpTrackingConsent: () => setJmpTrackingConsent,
|
|
49
|
+
subscribeJmpTrackingConsent: () => subscribeJmpTrackingConsent,
|
|
42
50
|
trackJmpServerPageView: () => trackJmpServerPageView
|
|
43
51
|
});
|
|
44
52
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -48,7 +56,6 @@ var JMP_SESSION_ID_KEY = "jmp_analytics_sid";
|
|
|
48
56
|
var JMP_LANDING_REFERER_KEY = "jmp_analytics_landing_referer";
|
|
49
57
|
var JMP_LANDING_REFERER_COOKIE = "jmp_lr";
|
|
50
58
|
var JMP_UTM_SESSION_KEY = "jmp_analytics_utm";
|
|
51
|
-
var JMP_EARLY_BEACON_PATH_KEY = "jmp_analytics_early_beacon_path";
|
|
52
59
|
var LANDING_REFERER_COOKIE_MAX_AGE_SEC = 30 * 60;
|
|
53
60
|
var JMP_UTM_PARAM_KEYS = [
|
|
54
61
|
"utm_source",
|
|
@@ -181,84 +188,207 @@ function getOrCreateSessionIdFromStorage() {
|
|
|
181
188
|
return void 0;
|
|
182
189
|
}
|
|
183
190
|
}
|
|
184
|
-
function
|
|
185
|
-
|
|
186
|
-
|
|
191
|
+
function buildLandingCaptureInlineScript() {
|
|
192
|
+
const cookieMaxAge = String(LANDING_REFERER_COOKIE_MAX_AGE_SEC);
|
|
193
|
+
return `(function(){try{var h=location.hostname;var ref=document.referrer||'';function rh(u){try{return new URL(u).hostname.replace(/^www\\./i,'').toLowerCase()}catch(e){try{return new URL('https://'+u).hostname.replace(/^www\\./i,'').toLowerCase()}catch(e2){return null}}}function ext(r){var x=rh(r);if(!x)return false;var s=h.replace(/^www\\./i,'').toLowerCase();return x!==s&&x.slice(-('.'+s).length)!==('.'+s)}function apexDom(hn){var s=hn.replace(/^www\\./i,'').toLowerCase();if(!s||s==='localhost'||/\\.local$/i.test(s)||s.indexOf('.')<0)return null;return s}function readCk(hn){var apex=apexDom(hn);if(!apex)return '';var pre='${JMP_LANDING_REFERER_COOKIE}=';var parts=document.cookie.split(';');for(var i=0;i<parts.length;i++){var t=parts[i].trim();if(t.indexOf(pre)===0){try{return decodeURIComponent(t.slice(pre.length)).trim()}catch(e){return ''}}}return ''}function writeCk(r,hn){var apex=apexDom(hn);if(!apex)return;var sec=location.protocol==='https:'?'; Secure':'';document.cookie='${JMP_LANDING_REFERER_COOKIE}='+encodeURIComponent(r.slice(0,2048))+'; Domain=.'+apex+'; Path=/; Max-Age=${cookieMaxAge}; SameSite=Lax'+sec}var stored=sessionStorage.getItem('${JMP_LANDING_REFERER_KEY}')||'';var ck=readCk(h);var preserved=stored||ck;var lr='';if(ref&&ext(ref)){sessionStorage.setItem('${JMP_LANDING_REFERER_KEY}',ref);writeCk(ref,h);lr=ref}else{lr=preserved||'';if(lr&&!stored)sessionStorage.setItem('${JMP_LANDING_REFERER_KEY}',lr)}var sid=sessionStorage.getItem('${JMP_SESSION_ID_KEY}');if(!sid&&crypto&&crypto.randomUUID){sid=crypto.randomUUID();sessionStorage.setItem('${JMP_SESSION_ID_KEY}',sid)}try{var sp=new URLSearchParams(location.search);var utm={};var updated=false;['utm_source','utm_medium','utm_campaign','utm_content','utm_term'].forEach(function(n){var v=sp.get(n);if(v){utm[n]=v;updated=true}});if(updated)sessionStorage.setItem('${JMP_UTM_SESSION_KEY}',JSON.stringify(utm))}catch(e){}}catch(e){}})();`;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// src/contact-link-classifier.ts
|
|
197
|
+
var BOOKING_LINK_HOSTS = [
|
|
198
|
+
"calendly.com",
|
|
199
|
+
"cal.com",
|
|
200
|
+
"acuityscheduling.com",
|
|
201
|
+
"calendar.google.com",
|
|
202
|
+
"calendar.app.google",
|
|
203
|
+
"bookings.microsoft.com",
|
|
204
|
+
"outlook.office.com",
|
|
205
|
+
"outlook.office365.com",
|
|
206
|
+
"book.ms",
|
|
207
|
+
"setmore.com",
|
|
208
|
+
"simplybook.me",
|
|
209
|
+
"oncehub.com",
|
|
210
|
+
"scheduleonce.com",
|
|
211
|
+
"youcanbook.me",
|
|
212
|
+
"savvycal.com",
|
|
213
|
+
"tidycal.com",
|
|
214
|
+
"zohobookings.com",
|
|
215
|
+
"square.site",
|
|
216
|
+
"squareup.com",
|
|
217
|
+
"meetings.hubspot.com",
|
|
218
|
+
"jobber.com",
|
|
219
|
+
"housecallpro.com",
|
|
220
|
+
"servicetitan.com",
|
|
221
|
+
"thryv.com",
|
|
222
|
+
"honeybook.com",
|
|
223
|
+
"dubsado.com",
|
|
224
|
+
"fresha.com",
|
|
225
|
+
"booksy.com",
|
|
226
|
+
"vagaro.com",
|
|
227
|
+
"mindbodyonline.com",
|
|
228
|
+
"mindbody.io",
|
|
229
|
+
"janeapp.com",
|
|
230
|
+
"cliniko.com",
|
|
231
|
+
"practicebetter.io"
|
|
232
|
+
];
|
|
233
|
+
var WHATSAPP_HOSTS = ["wa.me", "api.whatsapp.com", "whatsapp.com"];
|
|
234
|
+
function hostnameMatches(host, pattern) {
|
|
235
|
+
const h = host.toLowerCase();
|
|
236
|
+
const p = pattern.toLowerCase();
|
|
237
|
+
return h === p || h.endsWith(`.${p}`);
|
|
238
|
+
}
|
|
239
|
+
function isMapsHost(host, pathname) {
|
|
240
|
+
if (hostnameMatches(host, "maps.apple.com")) {
|
|
241
|
+
return true;
|
|
187
242
|
}
|
|
188
|
-
|
|
189
|
-
return
|
|
190
|
-
}
|
|
191
|
-
|
|
243
|
+
if (hostnameMatches(host, "maps.app.goo.gl")) {
|
|
244
|
+
return true;
|
|
245
|
+
}
|
|
246
|
+
if (hostnameMatches(host, "google.com") || hostnameMatches(host, "google.co")) {
|
|
247
|
+
return pathname === "/maps" || pathname.startsWith("/maps/") || pathname.startsWith("/local");
|
|
192
248
|
}
|
|
249
|
+
return false;
|
|
193
250
|
}
|
|
194
|
-
function
|
|
195
|
-
|
|
196
|
-
|
|
251
|
+
function isWhatsAppHost(host, pathname) {
|
|
252
|
+
for (const pattern of WHATSAPP_HOSTS) {
|
|
253
|
+
if (!hostnameMatches(host, pattern)) {
|
|
254
|
+
continue;
|
|
255
|
+
}
|
|
256
|
+
if (pattern === "whatsapp.com") {
|
|
257
|
+
return pathname.startsWith("/send");
|
|
258
|
+
}
|
|
259
|
+
return true;
|
|
197
260
|
}
|
|
261
|
+
return false;
|
|
262
|
+
}
|
|
263
|
+
function isBookingHost(host) {
|
|
264
|
+
for (const pattern of BOOKING_LINK_HOSTS) {
|
|
265
|
+
if (hostnameMatches(host, pattern)) {
|
|
266
|
+
return true;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
return false;
|
|
270
|
+
}
|
|
271
|
+
function classifyContactHref(href) {
|
|
272
|
+
const raw = href.trim();
|
|
273
|
+
if (!raw || raw.startsWith("#") || raw.startsWith("javascript:")) {
|
|
274
|
+
return null;
|
|
275
|
+
}
|
|
276
|
+
const lower = raw.toLowerCase();
|
|
277
|
+
if (lower.startsWith("tel:")) {
|
|
278
|
+
return { kind: "call" };
|
|
279
|
+
}
|
|
280
|
+
if (lower.startsWith("mailto:")) {
|
|
281
|
+
return { kind: "email" };
|
|
282
|
+
}
|
|
283
|
+
if (lower.startsWith("sms:") || lower.startsWith("smsto:")) {
|
|
284
|
+
return { kind: "contact_click", channel: "sms", linkHost: null };
|
|
285
|
+
}
|
|
286
|
+
if (lower.startsWith("geo:")) {
|
|
287
|
+
return { kind: "contact_click", channel: "maps", linkHost: null };
|
|
288
|
+
}
|
|
289
|
+
if (raw.startsWith("/") || raw.startsWith("?")) {
|
|
290
|
+
return null;
|
|
291
|
+
}
|
|
292
|
+
let url;
|
|
198
293
|
try {
|
|
199
|
-
|
|
294
|
+
url = new URL(raw);
|
|
200
295
|
} catch {
|
|
296
|
+
return null;
|
|
297
|
+
}
|
|
298
|
+
if (url.protocol !== "http:" && url.protocol !== "https:") {
|
|
299
|
+
return null;
|
|
300
|
+
}
|
|
301
|
+
const host = url.hostname.toLowerCase();
|
|
302
|
+
const pathname = url.pathname.toLowerCase();
|
|
303
|
+
if (isWhatsAppHost(host, pathname)) {
|
|
304
|
+
return { kind: "contact_click", channel: "whatsapp", linkHost: host };
|
|
201
305
|
}
|
|
306
|
+
if (isMapsHost(host, pathname)) {
|
|
307
|
+
return { kind: "contact_click", channel: "maps", linkHost: host };
|
|
308
|
+
}
|
|
309
|
+
if (isBookingHost(host)) {
|
|
310
|
+
return { kind: "contact_click", channel: "booking", linkHost: host };
|
|
311
|
+
}
|
|
312
|
+
return null;
|
|
202
313
|
}
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
314
|
+
|
|
315
|
+
// src/site-config.ts
|
|
316
|
+
var registeredSite = null;
|
|
317
|
+
function readNextPublicEnv(key) {
|
|
318
|
+
if (typeof process === "undefined" || !process.env) return void 0;
|
|
319
|
+
const v = key === "NEXT_PUBLIC_JMP_ANALYTICS_URL" ? process.env.NEXT_PUBLIC_JMP_ANALYTICS_URL : process.env.NEXT_PUBLIC_JMP_TRACKING_KEY;
|
|
320
|
+
return typeof v === "string" && v.length > 0 ? v : void 0;
|
|
321
|
+
}
|
|
322
|
+
function getServerConfigFromEnv() {
|
|
323
|
+
const baseUrl = readNextPublicEnv("NEXT_PUBLIC_JMP_ANALYTICS_URL");
|
|
324
|
+
const trackingKey = readNextPublicEnv("NEXT_PUBLIC_JMP_TRACKING_KEY");
|
|
325
|
+
if (!baseUrl || !trackingKey) return null;
|
|
326
|
+
return { baseUrl, trackingKey };
|
|
327
|
+
}
|
|
328
|
+
function defineJmpSite(definition) {
|
|
329
|
+
registeredSite = definition;
|
|
330
|
+
return definition;
|
|
331
|
+
}
|
|
332
|
+
function getJmpSiteDefinition() {
|
|
333
|
+
return registeredSite;
|
|
334
|
+
}
|
|
335
|
+
function getJmpContentConfig() {
|
|
336
|
+
const fromEnv = getServerConfigFromEnv();
|
|
337
|
+
if (!fromEnv) {
|
|
338
|
+
return null;
|
|
206
339
|
}
|
|
207
|
-
const
|
|
208
|
-
|
|
340
|
+
const site = getJmpSiteDefinition();
|
|
341
|
+
return {
|
|
342
|
+
...fromEnv,
|
|
343
|
+
contentWrappers: site?.contentWrappers ?? fromEnv.contentWrappers
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
// src/index.ts
|
|
348
|
+
var JMP_ANALYTICS_SDK_VERSION = "0.1.19";
|
|
349
|
+
var JMP_TRACKING_CONSENT_STORAGE_KEY = "jmp_analytics_consent_v1";
|
|
350
|
+
var moduleTrackingConsentGranted = true;
|
|
351
|
+
var trackingConsentListeners = /* @__PURE__ */ new Set();
|
|
352
|
+
function readStoredTrackingConsent() {
|
|
353
|
+
if (typeof window === "undefined") {
|
|
209
354
|
return false;
|
|
210
355
|
}
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
earlyBeacon: true,
|
|
216
|
-
...utm
|
|
217
|
-
};
|
|
218
|
-
if (landingReferer) {
|
|
219
|
-
metadata.referer = landingReferer;
|
|
356
|
+
try {
|
|
357
|
+
return localStorage.getItem(JMP_TRACKING_CONSENT_STORAGE_KEY) === "granted";
|
|
358
|
+
} catch {
|
|
359
|
+
return false;
|
|
220
360
|
}
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
"Content-Type": "application/json",
|
|
230
|
-
"X-JMP-Tracking-Key": args.trackingKey
|
|
361
|
+
}
|
|
362
|
+
function isJmpTrackingConsentGranted() {
|
|
363
|
+
return moduleTrackingConsentGranted;
|
|
364
|
+
}
|
|
365
|
+
function subscribeJmpTrackingConsent(listener) {
|
|
366
|
+
trackingConsentListeners.add(listener);
|
|
367
|
+
return () => {
|
|
368
|
+
trackingConsentListeners.delete(listener);
|
|
231
369
|
};
|
|
232
|
-
|
|
233
|
-
|
|
370
|
+
}
|
|
371
|
+
function setJmpTrackingConsent(granted) {
|
|
372
|
+
if (moduleTrackingConsentGranted === granted) {
|
|
373
|
+
return;
|
|
234
374
|
}
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
method: "POST",
|
|
238
|
-
headers,
|
|
239
|
-
body: JSON.stringify(payload),
|
|
240
|
-
keepalive: true,
|
|
241
|
-
mode: "cors",
|
|
242
|
-
credentials: "omit"
|
|
243
|
-
}).catch(() => {
|
|
375
|
+
moduleTrackingConsentGranted = granted;
|
|
376
|
+
if (typeof window !== "undefined") {
|
|
244
377
|
try {
|
|
245
|
-
|
|
378
|
+
localStorage.setItem(
|
|
379
|
+
JMP_TRACKING_CONSENT_STORAGE_KEY,
|
|
380
|
+
granted ? "granted" : "denied"
|
|
381
|
+
);
|
|
246
382
|
} catch {
|
|
247
383
|
}
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
const baseUrl = escapeInlineScript(args.baseUrl.replace(/\/$/, ""));
|
|
256
|
-
const trackingKey = escapeInlineScript(args.trackingKey);
|
|
257
|
-
const cookieMaxAge = String(LANDING_REFERER_COOKIE_MAX_AGE_SEC);
|
|
258
|
-
return `(function(){try{var k='${trackingKey}',b='${baseUrl}';if(!k||!b)return;var p=location.pathname+location.search||'/';var sentKey='${JMP_EARLY_BEACON_PATH_KEY}';if(sessionStorage.getItem(sentKey)===p)return;var h=location.hostname;var ref=document.referrer||'';function rh(u){try{return new URL(u).hostname.replace(/^www\\./i,'').toLowerCase()}catch(e){try{return new URL('https://'+u).hostname.replace(/^www\\./i,'').toLowerCase()}catch(e2){return null}}}function ext(r){var x=rh(r);if(!x)return false;var s=h.replace(/^www\\./i,'').toLowerCase();return x!==s&&x.slice(-('.'+s).length)!==('.'+s)}function apexDom(hn){var s=hn.replace(/^www\\./i,'').toLowerCase();if(!s||s==='localhost'||/\\.local$/i.test(s)||s.indexOf('.')<0)return null;return s}function readCk(hn){var apex=apexDom(hn);if(!apex)return '';var pre='${JMP_LANDING_REFERER_COOKIE}=';var parts=document.cookie.split(';');for(var i=0;i<parts.length;i++){var t=parts[i].trim();if(t.indexOf(pre)===0){try{return decodeURIComponent(t.slice(pre.length)).trim()}catch(e){return ''}}}return ''}function writeCk(r,hn){var apex=apexDom(hn);if(!apex)return;var sec=location.protocol==='https:'?'; Secure':'';document.cookie='${JMP_LANDING_REFERER_COOKIE}='+encodeURIComponent(r.slice(0,2048))+'; Domain=.'+apex+'; Path=/; Max-Age=${cookieMaxAge}; SameSite=Lax'+sec}var stored=sessionStorage.getItem('${JMP_LANDING_REFERER_KEY}')||'';var ck=readCk(h);var preserved=stored||ck;var lr='';if(ref&&ext(ref)){sessionStorage.setItem('${JMP_LANDING_REFERER_KEY}',ref);writeCk(ref,h);lr=ref}else{lr=preserved||'';if(lr&&!stored)sessionStorage.setItem('${JMP_LANDING_REFERER_KEY}',lr)}var sid=sessionStorage.getItem('${JMP_SESSION_ID_KEY}');if(!sid&&crypto&&crypto.randomUUID){sid=crypto.randomUUID();sessionStorage.setItem('${JMP_SESSION_ID_KEY}',sid)}var md={pageHostname:h,earlyBeacon:true};try{var sp=new URLSearchParams(location.search);['utm_source','utm_medium','utm_campaign','utm_content','utm_term'].forEach(function(n){var v=sp.get(n);if(v)md[n]=v})}catch(e){}if(lr)md.referer=lr;var body=JSON.stringify({type:'page_view',path:p,trackingKey:k,sessionId:sid||undefined,metadata:md});var hd={'Content-Type':'application/json','X-JMP-Tracking-Key':k};if(lr)hd['X-JMP-Visitor-Referer']=lr;sessionStorage.setItem(sentKey,p);fetch(b+'/api/events',{method:'POST',headers:hd,body:body,keepalive:true,mode:'cors',credentials:'omit'}).catch(function(){sessionStorage.removeItem(sentKey)})}catch(e){}})();`;
|
|
384
|
+
if (granted) {
|
|
385
|
+
captureLandingAttribution(window.location.hostname);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
for (const listener of trackingConsentListeners) {
|
|
389
|
+
listener();
|
|
390
|
+
}
|
|
259
391
|
}
|
|
260
|
-
|
|
261
|
-
// src/index.ts
|
|
262
392
|
function captureAndGetLandingReferer() {
|
|
263
393
|
if (typeof window === "undefined") {
|
|
264
394
|
return null;
|
|
@@ -333,9 +463,16 @@ function createJmpAnalytics(config) {
|
|
|
333
463
|
);
|
|
334
464
|
}
|
|
335
465
|
const fetchFn = resolvedFetch;
|
|
466
|
+
moduleTrackingConsentGranted = config.requireConsent ? readStoredTrackingConsent() : true;
|
|
467
|
+
function canSend() {
|
|
468
|
+
return moduleTrackingConsentGranted;
|
|
469
|
+
}
|
|
336
470
|
let lastDedupePath = "";
|
|
337
471
|
let lastDedupeAt = 0;
|
|
338
472
|
async function send(body) {
|
|
473
|
+
if (!canSend()) {
|
|
474
|
+
return;
|
|
475
|
+
}
|
|
339
476
|
const url = `${baseUrl}/api/events`;
|
|
340
477
|
const headers = {
|
|
341
478
|
"Content-Type": "application/json",
|
|
@@ -391,6 +528,9 @@ function createJmpAnalytics(config) {
|
|
|
391
528
|
}
|
|
392
529
|
}
|
|
393
530
|
async function sendLead(body) {
|
|
531
|
+
if (!canSend()) {
|
|
532
|
+
return;
|
|
533
|
+
}
|
|
394
534
|
const url = `${baseUrl}/api/leads`;
|
|
395
535
|
const headers = {
|
|
396
536
|
"Content-Type": "application/json",
|
|
@@ -453,6 +593,9 @@ function createJmpAnalytics(config) {
|
|
|
453
593
|
return false;
|
|
454
594
|
}
|
|
455
595
|
function trackPageView(options) {
|
|
596
|
+
if (!canSend()) {
|
|
597
|
+
return Promise.resolve();
|
|
598
|
+
}
|
|
456
599
|
const pathFromOptions = options?.path?.trim();
|
|
457
600
|
let pathname = "/";
|
|
458
601
|
let search = "";
|
|
@@ -468,9 +611,6 @@ function createJmpAnalytics(config) {
|
|
|
468
611
|
search = window.location.search.replace(/^\?/, "");
|
|
469
612
|
}
|
|
470
613
|
const path = search ? `${pathname}?${search}` : pathname;
|
|
471
|
-
if (wasEarlyBeaconSentForPath(path)) {
|
|
472
|
-
return Promise.resolve();
|
|
473
|
-
}
|
|
474
614
|
if (shouldDedupePageView(pathname)) {
|
|
475
615
|
return Promise.resolve();
|
|
476
616
|
}
|
|
@@ -521,6 +661,20 @@ function createJmpAnalytics(config) {
|
|
|
521
661
|
metadata: metadata ?? {}
|
|
522
662
|
});
|
|
523
663
|
}
|
|
664
|
+
function trackContactClick(path, options) {
|
|
665
|
+
const metadata = {
|
|
666
|
+
...options.metadata && typeof options.metadata === "object" ? options.metadata : {},
|
|
667
|
+
channel: options.channel
|
|
668
|
+
};
|
|
669
|
+
if (options.linkHost) {
|
|
670
|
+
metadata.linkHost = options.linkHost;
|
|
671
|
+
}
|
|
672
|
+
return send({
|
|
673
|
+
type: "contact_click",
|
|
674
|
+
path: path || "/",
|
|
675
|
+
metadata
|
|
676
|
+
});
|
|
677
|
+
}
|
|
524
678
|
function trackLead(options) {
|
|
525
679
|
const path = options?.path ?? (typeof window !== "undefined" ? window.location.pathname : "/");
|
|
526
680
|
const body = { path: path || "/" };
|
|
@@ -553,7 +707,20 @@ function createJmpAnalytics(config) {
|
|
|
553
707
|
if (type === "call_click") {
|
|
554
708
|
return trackCallClick(payload.path, payload.metadata);
|
|
555
709
|
}
|
|
556
|
-
|
|
710
|
+
if (type === "email_click") {
|
|
711
|
+
return trackEmailClick(payload.path, payload.metadata);
|
|
712
|
+
}
|
|
713
|
+
const meta = payload.metadata ?? {};
|
|
714
|
+
const channel = typeof meta.channel === "string" ? meta.channel : "";
|
|
715
|
+
const linkHost = typeof meta.linkHost === "string" ? meta.linkHost : null;
|
|
716
|
+
if (channel !== "sms" && channel !== "whatsapp" && channel !== "maps" && channel !== "booking") {
|
|
717
|
+
return Promise.resolve();
|
|
718
|
+
}
|
|
719
|
+
return trackContactClick(payload.path, {
|
|
720
|
+
channel,
|
|
721
|
+
linkHost,
|
|
722
|
+
metadata: meta
|
|
723
|
+
});
|
|
557
724
|
}
|
|
558
725
|
function subscribeToSpaNavigation() {
|
|
559
726
|
if (typeof window === "undefined") {
|
|
@@ -587,12 +754,75 @@ function createJmpAnalytics(config) {
|
|
|
587
754
|
history.replaceState = replace;
|
|
588
755
|
};
|
|
589
756
|
}
|
|
590
|
-
|
|
757
|
+
let lastContactClickKey = "";
|
|
758
|
+
let lastContactClickAt = 0;
|
|
759
|
+
function subscribeContactLinkAutoTrack() {
|
|
760
|
+
if (typeof window === "undefined" || typeof document === "undefined") {
|
|
761
|
+
return () => {
|
|
762
|
+
};
|
|
763
|
+
}
|
|
764
|
+
const handler = (event) => {
|
|
765
|
+
if (!canSend()) {
|
|
766
|
+
return;
|
|
767
|
+
}
|
|
768
|
+
const target = event.target;
|
|
769
|
+
if (!(target instanceof Element)) {
|
|
770
|
+
return;
|
|
771
|
+
}
|
|
772
|
+
const anchor = target.closest("a[href]");
|
|
773
|
+
if (!(anchor instanceof HTMLAnchorElement)) {
|
|
774
|
+
return;
|
|
775
|
+
}
|
|
776
|
+
if (anchor.closest("[data-jmp-no-track]")) {
|
|
777
|
+
return;
|
|
778
|
+
}
|
|
779
|
+
const href = anchor.getAttribute("href") ?? "";
|
|
780
|
+
const classified = classifyContactHref(href);
|
|
781
|
+
if (!classified) {
|
|
782
|
+
return;
|
|
783
|
+
}
|
|
784
|
+
const path = window.location.pathname;
|
|
785
|
+
if (classified.kind === "call") {
|
|
786
|
+
if (dedupeContactClick(`call_click:${path}`)) {
|
|
787
|
+
return;
|
|
788
|
+
}
|
|
789
|
+
void trackCallClick(path);
|
|
790
|
+
return;
|
|
791
|
+
}
|
|
792
|
+
if (classified.kind === "email") {
|
|
793
|
+
if (dedupeContactClick(`email_click:${path}`)) {
|
|
794
|
+
return;
|
|
795
|
+
}
|
|
796
|
+
void trackEmailClick(path);
|
|
797
|
+
return;
|
|
798
|
+
}
|
|
799
|
+
if (dedupeContactClick(`contact_click:${classified.channel}:${path}`)) {
|
|
800
|
+
return;
|
|
801
|
+
}
|
|
802
|
+
void trackContactClick(path, {
|
|
803
|
+
channel: classified.channel,
|
|
804
|
+
linkHost: classified.linkHost
|
|
805
|
+
});
|
|
806
|
+
};
|
|
807
|
+
document.addEventListener("click", handler, { capture: true });
|
|
808
|
+
return () => {
|
|
809
|
+
document.removeEventListener("click", handler, { capture: true });
|
|
810
|
+
};
|
|
811
|
+
}
|
|
812
|
+
function dedupeContactClick(key) {
|
|
813
|
+
const now = Date.now();
|
|
814
|
+
if (key === lastContactClickKey && now - lastContactClickAt < 1e3) {
|
|
815
|
+
return true;
|
|
816
|
+
}
|
|
817
|
+
lastContactClickKey = key;
|
|
818
|
+
lastContactClickAt = now;
|
|
819
|
+
return false;
|
|
820
|
+
}
|
|
821
|
+
if (typeof window !== "undefined" && canSend()) {
|
|
591
822
|
captureLandingAttribution(window.location.hostname);
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
});
|
|
823
|
+
}
|
|
824
|
+
if (typeof window !== "undefined" && config.autoTrackContactLinks && canSend()) {
|
|
825
|
+
subscribeContactLinkAutoTrack();
|
|
596
826
|
}
|
|
597
827
|
return {
|
|
598
828
|
track,
|
|
@@ -600,8 +830,12 @@ function createJmpAnalytics(config) {
|
|
|
600
830
|
trackFormSubmit,
|
|
601
831
|
trackCallClick,
|
|
602
832
|
trackEmailClick,
|
|
833
|
+
trackContactClick,
|
|
603
834
|
trackLead,
|
|
604
|
-
subscribeToSpaNavigation
|
|
835
|
+
subscribeToSpaNavigation,
|
|
836
|
+
subscribeContactLinkAutoTrack,
|
|
837
|
+
setTrackingConsent: setJmpTrackingConsent,
|
|
838
|
+
isTrackingConsentGranted: isJmpTrackingConsentGranted
|
|
605
839
|
};
|
|
606
840
|
}
|
|
607
841
|
async function trackJmpServerPageView(config, options = {}) {
|
|
@@ -691,11 +925,6 @@ function resolveContentWrappersFromConfig(config) {
|
|
|
691
925
|
if (config.contentWrappers?.length) {
|
|
692
926
|
return [...config.contentWrappers];
|
|
693
927
|
}
|
|
694
|
-
if (config.trustSlots?.length) {
|
|
695
|
-
return config.trustSlots.map(
|
|
696
|
-
(slot) => `trust.${slot}`
|
|
697
|
-
);
|
|
698
|
-
}
|
|
699
928
|
return [];
|
|
700
929
|
}
|
|
701
930
|
async function registerJmpContentWrappers(config) {
|
|
@@ -724,7 +953,10 @@ async function registerJmpContentWrappers(config) {
|
|
|
724
953
|
"Content-Type": "application/json",
|
|
725
954
|
"X-JMP-Tracking-Key": config.trackingKey
|
|
726
955
|
},
|
|
727
|
-
body: JSON.stringify({
|
|
956
|
+
body: JSON.stringify({
|
|
957
|
+
wrappers,
|
|
958
|
+
sdkVersion: JMP_ANALYTICS_SDK_VERSION
|
|
959
|
+
})
|
|
728
960
|
});
|
|
729
961
|
const text = await res.text();
|
|
730
962
|
if (!res.ok) {
|
|
@@ -742,18 +974,6 @@ async function registerJmpContentWrappers(config) {
|
|
|
742
974
|
const data = JSON.parse(text);
|
|
743
975
|
return { ok: true, wrappers: data.wrappers ?? wrappers };
|
|
744
976
|
}
|
|
745
|
-
async function registerJmpTrustCapabilities(config) {
|
|
746
|
-
const result = await registerJmpContentWrappers(config);
|
|
747
|
-
if (!result.ok) {
|
|
748
|
-
return result;
|
|
749
|
-
}
|
|
750
|
-
const slots = result.wrappers.filter((w) => w === "trust" || w.startsWith("trust.")).map((w) => w === "trust" ? "summary" : w.slice("trust.".length)).filter(
|
|
751
|
-
(s) => ["summary", "testimonials", "reviews", "stats", "logos", "credentials"].includes(
|
|
752
|
-
s
|
|
753
|
-
)
|
|
754
|
-
);
|
|
755
|
-
return { ok: true, slots };
|
|
756
|
-
}
|
|
757
977
|
function createJmpContentClient(config) {
|
|
758
978
|
return {
|
|
759
979
|
getBlogPosts: () => getJmpBlogPosts(config),
|
|
@@ -762,9 +982,7 @@ function createJmpContentClient(config) {
|
|
|
762
982
|
getTrustBundle: () => getJmpTrustBundle(config),
|
|
763
983
|
getSiteProfile: () => getJmpSiteProfile(config),
|
|
764
984
|
getRobotsTxt: () => getJmpRobotsTxt(config),
|
|
765
|
-
registerContentWrappers: () => registerJmpContentWrappers(config)
|
|
766
|
-
/** @deprecated Use registerContentWrappers */
|
|
767
|
-
registerTrustCapabilities: () => registerJmpTrustCapabilities(config)
|
|
985
|
+
registerContentWrappers: () => registerJmpContentWrappers(config)
|
|
768
986
|
};
|
|
769
987
|
}
|
|
770
988
|
async function getContent(config, path) {
|
|
@@ -813,31 +1031,49 @@ async function getContentText(config, path) {
|
|
|
813
1031
|
return text;
|
|
814
1032
|
}
|
|
815
1033
|
var DEFAULT_JMP_BROWSER_PAGE_VIEW_DEDUPE_MS = 800;
|
|
816
|
-
function
|
|
1034
|
+
function readNextPublicEnv2(key) {
|
|
817
1035
|
if (typeof process === "undefined" || !process.env) return void 0;
|
|
818
|
-
|
|
1036
|
+
let v;
|
|
1037
|
+
switch (key) {
|
|
1038
|
+
case "NEXT_PUBLIC_JMP_ANALYTICS_URL":
|
|
1039
|
+
v = process.env.NEXT_PUBLIC_JMP_ANALYTICS_URL;
|
|
1040
|
+
break;
|
|
1041
|
+
case "NEXT_PUBLIC_JMP_TRACKING_KEY":
|
|
1042
|
+
v = process.env.NEXT_PUBLIC_JMP_TRACKING_KEY;
|
|
1043
|
+
break;
|
|
1044
|
+
case "NEXT_PUBLIC_JMP_ANALYTICS_REQUIRE_CONSENT":
|
|
1045
|
+
v = process.env.NEXT_PUBLIC_JMP_ANALYTICS_REQUIRE_CONSENT;
|
|
1046
|
+
break;
|
|
1047
|
+
case "NEXT_PUBLIC_JMP_AUTO_CONTACT_LINKS":
|
|
1048
|
+
v = process.env.NEXT_PUBLIC_JMP_AUTO_CONTACT_LINKS;
|
|
1049
|
+
break;
|
|
1050
|
+
}
|
|
819
1051
|
return typeof v === "string" && v.length > 0 ? v : void 0;
|
|
820
1052
|
}
|
|
821
1053
|
function getJmpBrowserAnalyticsConfigFromEnv(overrides) {
|
|
822
|
-
const baseUrl =
|
|
823
|
-
const trackingKey =
|
|
1054
|
+
const baseUrl = readNextPublicEnv2("NEXT_PUBLIC_JMP_ANALYTICS_URL");
|
|
1055
|
+
const trackingKey = readNextPublicEnv2("NEXT_PUBLIC_JMP_TRACKING_KEY");
|
|
824
1056
|
if (!baseUrl || !trackingKey) return null;
|
|
1057
|
+
const requireConsentFromEnv = readNextPublicEnv2("NEXT_PUBLIC_JMP_ANALYTICS_REQUIRE_CONSENT") === "true";
|
|
1058
|
+
const autoTrackContactLinksFromEnv = readNextPublicEnv2("NEXT_PUBLIC_JMP_AUTO_CONTACT_LINKS") === "true";
|
|
825
1059
|
return {
|
|
826
1060
|
baseUrl,
|
|
827
1061
|
trackingKey,
|
|
828
1062
|
pageViewDedupeMs: DEFAULT_JMP_BROWSER_PAGE_VIEW_DEDUPE_MS,
|
|
829
|
-
...overrides
|
|
1063
|
+
...overrides,
|
|
1064
|
+
requireConsent: overrides?.requireConsent ?? requireConsentFromEnv,
|
|
1065
|
+
autoTrackContactLinks: overrides?.autoTrackContactLinks ?? autoTrackContactLinksFromEnv
|
|
830
1066
|
};
|
|
831
1067
|
}
|
|
832
1068
|
function getJmpServerContentConfigFromEnv(overrides) {
|
|
833
|
-
const baseUrl =
|
|
834
|
-
const trackingKey =
|
|
1069
|
+
const baseUrl = readNextPublicEnv2("NEXT_PUBLIC_JMP_ANALYTICS_URL");
|
|
1070
|
+
const trackingKey = readNextPublicEnv2("NEXT_PUBLIC_JMP_TRACKING_KEY");
|
|
835
1071
|
if (!baseUrl || !trackingKey) return null;
|
|
836
1072
|
return { baseUrl, trackingKey, ...overrides };
|
|
837
1073
|
}
|
|
838
1074
|
function isJmpBrowserAnalyticsEnvConfigured() {
|
|
839
1075
|
return Boolean(
|
|
840
|
-
|
|
1076
|
+
readNextPublicEnv2("NEXT_PUBLIC_JMP_ANALYTICS_URL") && readNextPublicEnv2("NEXT_PUBLIC_JMP_TRACKING_KEY")
|
|
841
1077
|
);
|
|
842
1078
|
}
|
|
843
1079
|
function isJmpServerContentEnvConfigured() {
|
|
@@ -859,25 +1095,33 @@ function createJmpContentClientFromServerEnv(overrides) {
|
|
|
859
1095
|
}
|
|
860
1096
|
// Annotate the CommonJS export names for ESM import in node:
|
|
861
1097
|
0 && (module.exports = {
|
|
1098
|
+
BOOKING_LINK_HOSTS,
|
|
862
1099
|
DEFAULT_JMP_BROWSER_PAGE_VIEW_DEDUPE_MS,
|
|
1100
|
+
JMP_ANALYTICS_SDK_VERSION,
|
|
1101
|
+
JMP_TRACKING_CONSENT_STORAGE_KEY,
|
|
863
1102
|
buildLandingCaptureInlineScript,
|
|
1103
|
+
classifyContactHref,
|
|
864
1104
|
createJmpAnalytics,
|
|
865
1105
|
createJmpContentClient,
|
|
866
1106
|
createJmpContentClientFromServerEnv,
|
|
1107
|
+
defineJmpSite,
|
|
867
1108
|
getJmpBlogPost,
|
|
868
1109
|
getJmpBlogPosts,
|
|
869
1110
|
getJmpBrowserAnalyticsConfigFromEnv,
|
|
1111
|
+
getJmpContentConfig,
|
|
870
1112
|
getJmpFaqs,
|
|
871
1113
|
getJmpRobotsTxt,
|
|
872
1114
|
getJmpServerContentConfigFromEnv,
|
|
1115
|
+
getJmpSiteDefinition,
|
|
873
1116
|
getJmpSiteProfile,
|
|
874
1117
|
getJmpTrustBundle,
|
|
875
1118
|
getOrCreateJmpAnalyticsFromBrowserEnv,
|
|
876
1119
|
isJmpBrowserAnalyticsEnvConfigured,
|
|
877
1120
|
isJmpServerContentEnvConfigured,
|
|
1121
|
+
isJmpTrackingConsentGranted,
|
|
878
1122
|
registerJmpContentWrappers,
|
|
879
|
-
|
|
880
|
-
|
|
1123
|
+
setJmpTrackingConsent,
|
|
1124
|
+
subscribeJmpTrackingConsent,
|
|
881
1125
|
trackJmpServerPageView
|
|
882
1126
|
});
|
|
883
1127
|
//# sourceMappingURL=index.cjs.map
|