@aranova/tracking-next 0.17.0 → 0.17.2
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 +35 -0
- package/dist/index.d.mts +38 -3
- package/dist/index.d.ts +38 -3
- package/dist/index.js +150 -89
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +150 -89
- package/dist/index.mjs.map +1 -1
- package/dist/middleware.js +8 -4
- package/dist/middleware.js.map +1 -1
- package/dist/middleware.mjs +8 -4
- package/dist/middleware.mjs.map +1 -1
- package/dist/phone.js +45 -41
- package/dist/phone.js.map +1 -1
- package/dist/phone.mjs +45 -41
- package/dist/phone.mjs.map +1 -1
- package/dist/sales.js.map +1 -1
- package/dist/sales.mjs.map +1 -1
- package/dist/server.js +8 -4
- package/dist/server.js.map +1 -1
- package/dist/server.mjs +8 -4
- package/dist/server.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -702,8 +702,8 @@ function thresholdMet(goal, eventType, metadata) {
|
|
|
702
702
|
return typeof metadata.page_name === "string" && metadata.page_name === t.page_name;
|
|
703
703
|
case "page_view":
|
|
704
704
|
case "form_start":
|
|
705
|
+
case "phone_click":
|
|
705
706
|
return true;
|
|
706
|
-
// no threshold — fire whenever the detector emits
|
|
707
707
|
default:
|
|
708
708
|
return false;
|
|
709
709
|
}
|
|
@@ -1040,6 +1040,27 @@ function getOrCreateTrackingClient(config) {
|
|
|
1040
1040
|
globalClientKey = key;
|
|
1041
1041
|
return globalClient;
|
|
1042
1042
|
}
|
|
1043
|
+
var clientCaptureRegistry = /* @__PURE__ */ new WeakMap();
|
|
1044
|
+
function attachClientCapturesOnce(client, build) {
|
|
1045
|
+
let entry = clientCaptureRegistry.get(client);
|
|
1046
|
+
if (entry === void 0) {
|
|
1047
|
+
entry = { detach: build(), refCount: 0 };
|
|
1048
|
+
clientCaptureRegistry.set(client, entry);
|
|
1049
|
+
}
|
|
1050
|
+
entry.refCount += 1;
|
|
1051
|
+
let released = false;
|
|
1052
|
+
return () => {
|
|
1053
|
+
if (released) return;
|
|
1054
|
+
released = true;
|
|
1055
|
+
const current = clientCaptureRegistry.get(client);
|
|
1056
|
+
if (current === void 0) return;
|
|
1057
|
+
current.refCount -= 1;
|
|
1058
|
+
if (current.refCount <= 0) {
|
|
1059
|
+
current.detach();
|
|
1060
|
+
clientCaptureRegistry.delete(client);
|
|
1061
|
+
}
|
|
1062
|
+
};
|
|
1063
|
+
}
|
|
1043
1064
|
function createTrackingClient(config) {
|
|
1044
1065
|
const flushIntervalMs = config.flushIntervalMs ?? DEFAULT_FLUSH_INTERVAL_MS;
|
|
1045
1066
|
const maxQueueSize = Math.min(config.maxQueueSize ?? DEFAULT_MAX_QUEUE_SIZE, HARD_MAX_BATCH);
|
|
@@ -1324,7 +1345,11 @@ var phoneClickMetadataSchema = z8.object({
|
|
|
1324
1345
|
}).strict(),
|
|
1325
1346
|
section: z8.string().nullable().optional()
|
|
1326
1347
|
}).strict();
|
|
1327
|
-
var phoneClickConfigSchema = z8.object({
|
|
1348
|
+
var phoneClickConfigSchema = z8.object({
|
|
1349
|
+
autoCapture: z8.object({
|
|
1350
|
+
selector: z8.string().optional()
|
|
1351
|
+
}).strict().optional()
|
|
1352
|
+
}).strict();
|
|
1328
1353
|
|
|
1329
1354
|
// ../tracking-core/src/events/scroll-depth.ts
|
|
1330
1355
|
import { z as z9 } from "zod";
|
|
@@ -1825,6 +1850,99 @@ function attachCtaClickCapture(client, config) {
|
|
|
1825
1850
|
};
|
|
1826
1851
|
}
|
|
1827
1852
|
|
|
1853
|
+
// ../tracking-core/src/phone.ts
|
|
1854
|
+
import { AsYouType, parsePhoneNumberFromString } from "libphonenumber-js";
|
|
1855
|
+
var DEFAULT_PHONE_COUNTRY = "CA";
|
|
1856
|
+
function parsePhone(raw, country) {
|
|
1857
|
+
const region = country ?? DEFAULT_PHONE_COUNTRY;
|
|
1858
|
+
const parsed = parsePhoneNumberFromString(raw ?? "", region);
|
|
1859
|
+
if (!parsed) {
|
|
1860
|
+
return { e164: null, national: "", international: "", country: region, isValid: false };
|
|
1861
|
+
}
|
|
1862
|
+
const isValid = parsed.isValid();
|
|
1863
|
+
return {
|
|
1864
|
+
// E.164 is only surfaced for a *valid* number — a possible-but-invalid input
|
|
1865
|
+
// (e.g. too few digits) still parses but must not be transmitted.
|
|
1866
|
+
e164: isValid ? parsed.number : null,
|
|
1867
|
+
national: parsed.formatNational(),
|
|
1868
|
+
international: parsed.formatInternational(),
|
|
1869
|
+
country: parsed.country ?? region,
|
|
1870
|
+
isValid
|
|
1871
|
+
};
|
|
1872
|
+
}
|
|
1873
|
+
function toE164(raw, country) {
|
|
1874
|
+
return parsePhone(raw, country).e164;
|
|
1875
|
+
}
|
|
1876
|
+
function formatPhone(value, format = "national", country) {
|
|
1877
|
+
const parsed = parsePhone(value, country);
|
|
1878
|
+
if (typeof format === "function") return format(parsed);
|
|
1879
|
+
switch (format) {
|
|
1880
|
+
case "international":
|
|
1881
|
+
return parsed.international || value;
|
|
1882
|
+
case "e164":
|
|
1883
|
+
return parsed.e164 ?? value;
|
|
1884
|
+
case "national":
|
|
1885
|
+
default:
|
|
1886
|
+
return parsed.national || value;
|
|
1887
|
+
}
|
|
1888
|
+
}
|
|
1889
|
+
function formatPhoneAsTyped(raw, country) {
|
|
1890
|
+
return new AsYouType(country ?? DEFAULT_PHONE_COUNTRY).input(raw ?? "");
|
|
1891
|
+
}
|
|
1892
|
+
|
|
1893
|
+
// ../tracking-core/src/triggers/phone-click-capture.ts
|
|
1894
|
+
var DEFAULT_TEL_SELECTOR = 'a[href^="tel:"]';
|
|
1895
|
+
function safeDecodeURIComponent(value) {
|
|
1896
|
+
try {
|
|
1897
|
+
return decodeURIComponent(value);
|
|
1898
|
+
} catch {
|
|
1899
|
+
return value;
|
|
1900
|
+
}
|
|
1901
|
+
}
|
|
1902
|
+
function resolvePhoneNumber(el) {
|
|
1903
|
+
const href = el instanceof HTMLAnchorElement ? el.href : el.getAttribute("href") ?? "";
|
|
1904
|
+
const raw = safeDecodeURIComponent(href.replace(/^tel:/i, "").split(";")[0]).trim();
|
|
1905
|
+
return toE164(raw) ?? raw;
|
|
1906
|
+
}
|
|
1907
|
+
function attachPhoneClickCapture(client, config) {
|
|
1908
|
+
if (typeof window === "undefined" || typeof document === "undefined") {
|
|
1909
|
+
return () => {
|
|
1910
|
+
};
|
|
1911
|
+
}
|
|
1912
|
+
const autoCapture = config.autoCapture;
|
|
1913
|
+
if (!autoCapture) {
|
|
1914
|
+
return () => {
|
|
1915
|
+
};
|
|
1916
|
+
}
|
|
1917
|
+
const selector = autoCapture.selector ?? DEFAULT_TEL_SELECTOR;
|
|
1918
|
+
function onClick(event) {
|
|
1919
|
+
const target = event.target;
|
|
1920
|
+
if (!(target instanceof Element)) return;
|
|
1921
|
+
let matched = null;
|
|
1922
|
+
try {
|
|
1923
|
+
matched = target.closest(selector);
|
|
1924
|
+
} catch {
|
|
1925
|
+
return;
|
|
1926
|
+
}
|
|
1927
|
+
if (matched === null) return;
|
|
1928
|
+
const metadata = {
|
|
1929
|
+
phone_number: resolvePhoneNumber(matched),
|
|
1930
|
+
page: { path: window.location.pathname },
|
|
1931
|
+
section: matched.getAttribute("data-aranova-section")
|
|
1932
|
+
};
|
|
1933
|
+
client.trackEvent({
|
|
1934
|
+
eventType: "phone_click",
|
|
1935
|
+
metadata,
|
|
1936
|
+
pageUrl: window.location.href,
|
|
1937
|
+
occurredAt: null
|
|
1938
|
+
});
|
|
1939
|
+
}
|
|
1940
|
+
document.addEventListener("click", onClick, true);
|
|
1941
|
+
return () => {
|
|
1942
|
+
document.removeEventListener("click", onClick, true);
|
|
1943
|
+
};
|
|
1944
|
+
}
|
|
1945
|
+
|
|
1828
1946
|
// ../tracking-core/src/resources/sales/errors.ts
|
|
1829
1947
|
var AranovaApiError = class extends Error {
|
|
1830
1948
|
constructor(message, options) {
|
|
@@ -2152,46 +2270,6 @@ async function fetchServices(config) {
|
|
|
2152
2270
|
return salesRequest(config, "GET", "/services");
|
|
2153
2271
|
}
|
|
2154
2272
|
|
|
2155
|
-
// ../tracking-core/src/phone.ts
|
|
2156
|
-
import { AsYouType, parsePhoneNumberFromString } from "libphonenumber-js";
|
|
2157
|
-
var DEFAULT_PHONE_COUNTRY = "CA";
|
|
2158
|
-
function parsePhone(raw, country) {
|
|
2159
|
-
const region = country ?? DEFAULT_PHONE_COUNTRY;
|
|
2160
|
-
const parsed = parsePhoneNumberFromString(raw ?? "", region);
|
|
2161
|
-
if (!parsed) {
|
|
2162
|
-
return { e164: null, national: "", international: "", country: region, isValid: false };
|
|
2163
|
-
}
|
|
2164
|
-
const isValid = parsed.isValid();
|
|
2165
|
-
return {
|
|
2166
|
-
// E.164 is only surfaced for a *valid* number — a possible-but-invalid input
|
|
2167
|
-
// (e.g. too few digits) still parses but must not be transmitted.
|
|
2168
|
-
e164: isValid ? parsed.number : null,
|
|
2169
|
-
national: parsed.formatNational(),
|
|
2170
|
-
international: parsed.formatInternational(),
|
|
2171
|
-
country: parsed.country ?? region,
|
|
2172
|
-
isValid
|
|
2173
|
-
};
|
|
2174
|
-
}
|
|
2175
|
-
function toE164(raw, country) {
|
|
2176
|
-
return parsePhone(raw, country).e164;
|
|
2177
|
-
}
|
|
2178
|
-
function formatPhone(value, format = "national", country) {
|
|
2179
|
-
const parsed = parsePhone(value, country);
|
|
2180
|
-
if (typeof format === "function") return format(parsed);
|
|
2181
|
-
switch (format) {
|
|
2182
|
-
case "international":
|
|
2183
|
-
return parsed.international || value;
|
|
2184
|
-
case "e164":
|
|
2185
|
-
return parsed.e164 ?? value;
|
|
2186
|
-
case "national":
|
|
2187
|
-
default:
|
|
2188
|
-
return parsed.national || value;
|
|
2189
|
-
}
|
|
2190
|
-
}
|
|
2191
|
-
function formatPhoneAsTyped(raw, country) {
|
|
2192
|
-
return new AsYouType(country ?? DEFAULT_PHONE_COUNTRY).input(raw ?? "");
|
|
2193
|
-
}
|
|
2194
|
-
|
|
2195
2273
|
// ../tracking-core/src/phone-field.ts
|
|
2196
2274
|
function phoneField(name, raw, country) {
|
|
2197
2275
|
return { name, type: "phone", value: toE164(raw, country) };
|
|
@@ -2528,7 +2606,7 @@ function GoogleAdsTracking(props) {
|
|
|
2528
2606
|
import { usePathname, useSearchParams } from "next/navigation";
|
|
2529
2607
|
|
|
2530
2608
|
// package.json
|
|
2531
|
-
var version = "0.17.
|
|
2609
|
+
var version = "0.17.2";
|
|
2532
2610
|
|
|
2533
2611
|
// src/factory.tsx
|
|
2534
2612
|
import {
|
|
@@ -2742,33 +2820,6 @@ function createTracking(options) {
|
|
|
2742
2820
|
});
|
|
2743
2821
|
}
|
|
2744
2822
|
}, [pathname]);
|
|
2745
|
-
useEffect3(() => {
|
|
2746
|
-
const rawClient = getOrCreateTrackingClient({
|
|
2747
|
-
apiKey,
|
|
2748
|
-
endpoint,
|
|
2749
|
-
surface: "next",
|
|
2750
|
-
packageName: "@aranova/tracking-next",
|
|
2751
|
-
triggers,
|
|
2752
|
-
environment,
|
|
2753
|
-
activeGtagIds: gtagIds,
|
|
2754
|
-
debug
|
|
2755
|
-
});
|
|
2756
|
-
return attachBfcacheRestore(wrapClient(rawClient));
|
|
2757
|
-
}, []);
|
|
2758
|
-
useEffect3(() => {
|
|
2759
|
-
if (!timeOnSiteConfig) return;
|
|
2760
|
-
const rawClient = getOrCreateTrackingClient({
|
|
2761
|
-
apiKey,
|
|
2762
|
-
endpoint,
|
|
2763
|
-
surface: "next",
|
|
2764
|
-
packageName: "@aranova/tracking-next",
|
|
2765
|
-
triggers,
|
|
2766
|
-
environment,
|
|
2767
|
-
activeGtagIds: gtagIds,
|
|
2768
|
-
debug
|
|
2769
|
-
});
|
|
2770
|
-
return attachTimeOnSite(wrapClient(rawClient), timeOnSiteConfig);
|
|
2771
|
-
}, []);
|
|
2772
2823
|
const multiPageSessionConfig = triggers.automatic.multi_page_session ?? null;
|
|
2773
2824
|
const mpsLastPathRef = useRef(null);
|
|
2774
2825
|
useEffect3(() => {
|
|
@@ -2819,7 +2870,6 @@ function createTracking(options) {
|
|
|
2819
2870
|
}
|
|
2820
2871
|
}, [pathname]);
|
|
2821
2872
|
useEffect3(() => {
|
|
2822
|
-
const detachers = [];
|
|
2823
2873
|
const rawClient = getOrCreateTrackingClient({
|
|
2824
2874
|
apiKey,
|
|
2825
2875
|
endpoint,
|
|
@@ -2830,25 +2880,36 @@ function createTracking(options) {
|
|
|
2830
2880
|
activeGtagIds: gtagIds,
|
|
2831
2881
|
debug
|
|
2832
2882
|
});
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
detachers.push(
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
2883
|
+
return attachClientCapturesOnce(rawClient, () => {
|
|
2884
|
+
const detachers = [];
|
|
2885
|
+
const detectorClient = wrapClient(rawClient);
|
|
2886
|
+
detachers.push(attachPageExit(detectorClient));
|
|
2887
|
+
detachers.push(attachBfcacheRestore(detectorClient));
|
|
2888
|
+
if (timeOnSiteConfig) {
|
|
2889
|
+
detachers.push(attachTimeOnSite(detectorClient, timeOnSiteConfig));
|
|
2890
|
+
}
|
|
2891
|
+
const scrollDepth = triggers.automatic.scroll_depth;
|
|
2892
|
+
if (scrollDepth) {
|
|
2893
|
+
detachers.push(attachScrollDepth(detectorClient, scrollDepth));
|
|
2894
|
+
}
|
|
2895
|
+
const formStart = triggers.automatic.form_start;
|
|
2896
|
+
if (formStart) {
|
|
2897
|
+
detachers.push(attachFormStart(detectorClient, formStart));
|
|
2898
|
+
}
|
|
2899
|
+
const ctaClick = triggers.manual?.cta_click;
|
|
2900
|
+
if (ctaClick) {
|
|
2901
|
+
detachers.push(attachCtaClickCapture(detectorClient, ctaClick));
|
|
2850
2902
|
}
|
|
2851
|
-
|
|
2903
|
+
const phoneClick = triggers.manual?.phone_click;
|
|
2904
|
+
if (phoneClick) {
|
|
2905
|
+
detachers.push(attachPhoneClickCapture(detectorClient, phoneClick));
|
|
2906
|
+
}
|
|
2907
|
+
return () => {
|
|
2908
|
+
for (let i = detachers.length - 1; i >= 0; i--) {
|
|
2909
|
+
detachers[i]();
|
|
2910
|
+
}
|
|
2911
|
+
};
|
|
2912
|
+
});
|
|
2852
2913
|
}, []);
|
|
2853
2914
|
return /* @__PURE__ */ jsxs4(TrackingContext.Provider, { value: client, children: [
|
|
2854
2915
|
/* @__PURE__ */ jsx5(Suspense, { fallback: null, children: /* @__PURE__ */ jsx5(PageViewTracker, { fire: firePageView }) }),
|