@pack/packlytics 0.0.1-ab-beta.2.0

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.
Files changed (38) hide show
  1. package/README.md +11 -0
  2. package/dist/index.d.ts +3 -0
  3. package/dist/index.d.ts.map +1 -0
  4. package/dist/index.js +2 -0
  5. package/dist/packlytics.d.ts +5 -0
  6. package/dist/packlytics.d.ts.map +1 -0
  7. package/dist/packlytics.js +39 -0
  8. package/dist/packlytics.types.d.ts +26 -0
  9. package/dist/packlytics.types.d.ts.map +1 -0
  10. package/dist/packlytics.types.js +1 -0
  11. package/dist/utils/get-client-device.d.ts +13 -0
  12. package/dist/utils/get-client-device.d.ts.map +1 -0
  13. package/dist/utils/get-client-device.js +16 -0
  14. package/dist/utils/get-client-ip-address.d.ts +30 -0
  15. package/dist/utils/get-client-ip-address.d.ts.map +1 -0
  16. package/dist/utils/get-client-ip-address.js +50 -0
  17. package/dist/utils/get-client-locales.d.ts +19 -0
  18. package/dist/utils/get-client-locales.d.ts.map +1 -0
  19. package/dist/utils/get-client-locales.js +18 -0
  20. package/dist/utils/get-headers.d.ts +2 -0
  21. package/dist/utils/get-headers.d.ts.map +1 -0
  22. package/dist/utils/get-headers.js +6 -0
  23. package/dist/utils/get-packlytics-id.d.ts +12 -0
  24. package/dist/utils/get-packlytics-id.d.ts.map +1 -0
  25. package/dist/utils/get-packlytics-id.js +36 -0
  26. package/dist/utils/page-hit.d.ts +3 -0
  27. package/dist/utils/page-hit.d.ts.map +1 -0
  28. package/dist/utils/page-hit.js +6 -0
  29. package/dist/utils/sanatize-payload.d.ts +2 -0
  30. package/dist/utils/sanatize-payload.d.ts.map +1 -0
  31. package/dist/utils/sanatize-payload.js +30 -0
  32. package/dist/utils/send-event.d.ts +3 -0
  33. package/dist/utils/send-event.d.ts.map +1 -0
  34. package/dist/utils/send-event.js +61 -0
  35. package/dist/utils/timezone-country-map.d.ts +2 -0
  36. package/dist/utils/timezone-country-map.d.ts.map +1 -0
  37. package/dist/utils/timezone-country-map.js +428 -0
  38. package/package.json +37 -0
package/README.md ADDED
@@ -0,0 +1,11 @@
1
+ # packlytics
2
+
3
+ ````
4
+ yarn install
5
+ ````
6
+
7
+ ````
8
+ yarn build && ~/.yarn/bin/yalc publish
9
+ ````
10
+
11
+ s
@@ -0,0 +1,3 @@
1
+ export * from "./packlytics.types";
2
+ export * from "./packlytics";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC;AACnC,cAAc,cAAc,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export * from "./packlytics.types";
2
+ export * from "./packlytics";
@@ -0,0 +1,5 @@
1
+ export declare function packlytics(request: Request, session: any, params: {
2
+ storeFrontId: string;
3
+ sessionSecret: string;
4
+ }): Promise<Response | undefined>;
5
+ //# sourceMappingURL=packlytics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"packlytics.d.ts","sourceRoot":"","sources":["../src/packlytics.ts"],"names":[],"mappings":"AAMA,wBAAsB,UAAU,CAC9B,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,GAAG,EACZ,MAAM,EAAE;IACN,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;CACvB,iCA8CF"}
@@ -0,0 +1,39 @@
1
+ import { getPacklyticsId } from "./utils/get-packlytics-id";
2
+ import { getClientLocales } from "./utils/get-client-locales";
3
+ import { trackPageHit } from "./utils/page-hit";
4
+ import { getDevice } from "./utils/get-client-device";
5
+ import { getStorefrontHeaders } from "@shopify/remix-oxygen";
6
+ export async function packlytics(request, session, params) {
7
+ if (process.env.NODE_ENV === "development") {
8
+ return;
9
+ }
10
+ // Preview enabled
11
+ if (!!session.get("enabled")) {
12
+ return;
13
+ }
14
+ const url = new URL(request.url);
15
+ const ipaddress = getStorefrontHeaders(request)["buyerIp"] || "";
16
+ const dataToHash = `${request.headers.get("user-agent")}${ipaddress}${url.hostname}`;
17
+ const packlyticsId = getPacklyticsId(dataToHash, params.sessionSecret);
18
+ const testSession = session.get("test");
19
+ return trackPageHit(params.storeFrontId, packlyticsId)({
20
+ "pack-session-id": session.id, // This session ID is saved on the __pack cookie
21
+ "user-agent": request.headers.get("user-agent") || "",
22
+ pathname: url.pathname,
23
+ query: url.search,
24
+ hostname: url.hostname,
25
+ referrer: request.referrer,
26
+ ipaddress: ipaddress,
27
+ language: getClientLocales(request) || "",
28
+ locale: request.headers.get("accept-language") || "",
29
+ connection: request.headers.get("connection") || "",
30
+ href: request.url,
31
+ ...getDevice(request.headers.get("user-agent") || ""),
32
+ test: {
33
+ "test-id": testSession?.data?.id || "",
34
+ "test-handle": testSession?.data?.handle || "",
35
+ "test-variant-id": testSession?.data?.TestVariant?.id || "",
36
+ "test-variant-handle": testSession?.data?.TestVariant?.handle || "",
37
+ },
38
+ });
39
+ }
@@ -0,0 +1,26 @@
1
+ declare global {
2
+ interface Window {
3
+ __nightmare: any;
4
+ Cypress: any;
5
+ }
6
+ }
7
+ type JSONValue = string | number | boolean | JSONObject | JSONArray;
8
+ interface JSONArray extends Array<JSONValue> {
9
+ }
10
+ interface JSONObject {
11
+ [x: string]: JSONValue;
12
+ }
13
+ export type PackData = {
14
+ version: string;
15
+ };
16
+ export type EventDataPayload = JSONObject;
17
+ export type EventData = PackData & {
18
+ timestamp: string;
19
+ action: string;
20
+ storefront_id: string;
21
+ session_id: string;
22
+ payload: string;
23
+ };
24
+ export type PageViewEvent = EventDataPayload;
25
+ export {};
26
+ //# sourceMappingURL=packlytics.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"packlytics.types.d.ts","sourceRoot":"","sources":["../src/packlytics.types.ts"],"names":[],"mappings":"AAAA,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,WAAW,EAAE,GAAG,CAAC;QACjB,OAAO,EAAE,GAAG,CAAC;KACd;CACF;AAED,KAAK,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,UAAU,GAAG,SAAS,CAAC;AAEpE,UAAU,SAAU,SAAQ,KAAK,CAAC,SAAS,CAAC;CAAG;AAE/C,UAAU,UAAU;IAClB,CAAC,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACxB;AAED,MAAM,MAAM,QAAQ,GAAG;IACrB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG,UAAU,CAAC;AAE1C,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG,gBAAgB,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,13 @@
1
+ export declare function getDevice(userAgent: string): {
2
+ deviceType: string;
3
+ deviceModel: string;
4
+ deviceVendor: string;
5
+ os: string;
6
+ osVersion: string;
7
+ browser: string;
8
+ browserVersion: string;
9
+ engine: string;
10
+ engineVersion: string;
11
+ cpu: string;
12
+ };
13
+ //# sourceMappingURL=get-client-device.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-client-device.d.ts","sourceRoot":"","sources":["../../src/utils/get-client-device.ts"],"names":[],"mappings":"AAEA,wBAAgB,SAAS,CAAC,SAAS,EAAE,MAAM;;;;;;;;;;;EAe1C"}
@@ -0,0 +1,16 @@
1
+ import parser from "ua-parser-js";
2
+ export function getDevice(userAgent) {
3
+ const userAgentData = parser(userAgent);
4
+ return {
5
+ deviceType: userAgentData.device.type || "desktop",
6
+ deviceModel: userAgentData.device.model || "unknown",
7
+ deviceVendor: userAgentData.device.vendor || "unknown",
8
+ os: userAgentData.os.name || "unknown",
9
+ osVersion: userAgentData.os.version || "unknown",
10
+ browser: userAgentData.browser.name || "unknown",
11
+ browserVersion: userAgentData.browser.version || "unknown",
12
+ engine: userAgentData.engine.name || "unknown",
13
+ engineVersion: userAgentData.engine.version || "unknown",
14
+ cpu: userAgentData.cpu.architecture || "unknown",
15
+ };
16
+ }
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Get the IP address of the client sending a request.
3
+ *
4
+ * It receives the Request object or the headers object and use it to get the
5
+ * IP address from one of the following headers in order.
6
+ *
7
+ * - X-Client-IP
8
+ * - X-Forwarded-For
9
+ * - HTTP-X-Forwarded-For
10
+ * - Fly-Client-IP
11
+ * - CF-Connecting-IP
12
+ * - Fastly-Client-Ip
13
+ * - True-Client-Ip
14
+ * - X-Real-IP
15
+ * - X-Cluster-Client-IP
16
+ * - X-Forwarded
17
+ * - Forwarded-For
18
+ * - Forwarded
19
+ * - DO-Connecting-IP
20
+ * - oxygen-buyer-ip
21
+ *
22
+ * If the IP address is valid, it will be returned. Otherwise, null will be
23
+ * returned.
24
+ *
25
+ * If the header values contains more than one IP address, the first valid one
26
+ * will be returned.
27
+ */
28
+ export declare function getClientIPAddress(headers: Headers): string | null;
29
+ export declare function getClientIPAddress(request: Request): string | null;
30
+ //# sourceMappingURL=get-client-ip-address.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-client-ip-address.d.ts","sourceRoot":"","sources":["../../src/utils/get-client-ip-address.ts"],"names":[],"mappings":"AAwBA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAAC;AACpE,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAAC"}
@@ -0,0 +1,50 @@
1
+ import { isIP } from "is-ip";
2
+ import { getHeaders } from "./get-headers.js";
3
+ /**
4
+ * This is the list of headers, in order of preference, that will be used to
5
+ * determine the client's IP address.
6
+ */
7
+ const headerNames = Object.freeze([
8
+ "X-Client-IP",
9
+ "X-Forwarded-For",
10
+ "HTTP-X-Forwarded-For",
11
+ "Fly-Client-IP",
12
+ "CF-Connecting-IP",
13
+ "Fastly-Client-Ip",
14
+ "True-Client-Ip",
15
+ "X-Real-IP",
16
+ "X-Cluster-Client-IP",
17
+ "X-Forwarded",
18
+ "Forwarded-For",
19
+ "Forwarded",
20
+ "DO-Connecting-IP" /** Digital ocean app platform */,
21
+ "oxygen-buyer-ip" /** Shopify oxygen platform */,
22
+ ]);
23
+ export function getClientIPAddress(requestOrHeaders) {
24
+ let headers = getHeaders(requestOrHeaders);
25
+ let ipAddress = headerNames
26
+ .flatMap((headerName) => {
27
+ let value = headers.get(headerName);
28
+ if (headerName === "Forwarded") {
29
+ return parseForwardedHeader(value);
30
+ }
31
+ if (!value?.includes(","))
32
+ return value;
33
+ return value.split(",").map((ip) => ip.trim());
34
+ })
35
+ .find((ip) => {
36
+ if (ip === null)
37
+ return false;
38
+ return isIP(ip);
39
+ });
40
+ return ipAddress ?? null;
41
+ }
42
+ function parseForwardedHeader(value) {
43
+ if (!value)
44
+ return null;
45
+ for (let part of value.split(";")) {
46
+ if (part.startsWith("for="))
47
+ return part.slice(4);
48
+ }
49
+ return null;
50
+ }
@@ -0,0 +1,19 @@
1
+ export type Locales = string[] | undefined;
2
+ /**
3
+ * Get the client's locales from the Accept-Language header.
4
+ * If the header is not defined returns null.
5
+ * If the header is defined return an array of locales, sorted by the quality
6
+ * value.
7
+ *
8
+ * @example
9
+ * export async function loader({ request }: LoaderArgs) {
10
+ * let locales = getClientLocales(request)
11
+ * let date = new Date().toLocaleDateString(locales, {
12
+ * "day": "numeric",
13
+ * });
14
+ * return json({ date })
15
+ * }
16
+ */
17
+ export declare function getClientLocales(headers: Headers): Locales;
18
+ export declare function getClientLocales(request: Request): Locales;
19
+ //# sourceMappingURL=get-client-locales.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-client-locales.d.ts","sourceRoot":"","sources":["../../src/utils/get-client-locales.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,OAAO,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC;AAE3C;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC;AAC5D,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC"}
@@ -0,0 +1,18 @@
1
+ import { parseAcceptLanguage } from "intl-parse-accept-language";
2
+ import { getHeaders } from "./get-headers.js";
3
+ export function getClientLocales(requestOrHeaders) {
4
+ let headers = getHeaders(requestOrHeaders);
5
+ let acceptLanguage = headers.get("Accept-Language");
6
+ // if the header is not defined, return undefined
7
+ if (!acceptLanguage)
8
+ return undefined;
9
+ let locales = parseAcceptLanguage(acceptLanguage, {
10
+ validate: Intl.DateTimeFormat.supportedLocalesOf,
11
+ ignoreWildcard: true,
12
+ });
13
+ // if there are no locales found, return undefined
14
+ if (locales.length === 0)
15
+ return undefined;
16
+ // if there are multiple locales, return the array
17
+ return locales;
18
+ }
@@ -0,0 +1,2 @@
1
+ export declare function getHeaders(requestOrHeaders: Request | Headers): Headers;
2
+ //# sourceMappingURL=get-headers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-headers.d.ts","sourceRoot":"","sources":["../../src/utils/get-headers.ts"],"names":[],"mappings":"AAAA,wBAAgB,UAAU,CAAC,gBAAgB,EAAE,OAAO,GAAG,OAAO,GAAG,OAAO,CAMvE"}
@@ -0,0 +1,6 @@
1
+ export function getHeaders(requestOrHeaders) {
2
+ if (requestOrHeaders instanceof Request) {
3
+ return requestOrHeaders.headers;
4
+ }
5
+ return requestOrHeaders;
6
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Generates a UUID from the user data, such as user-agent and IP Address + Salt
3
+ * The salt is generated on the currante date + a Secret from the StoreFront,
4
+ * So this UUID will be regenerated every day.
5
+ *
6
+ * We can never use this id to trace back users for GDPR compliance.
7
+ *
8
+ * @param data
9
+ * @param secret
10
+ */
11
+ export declare function getPacklyticsId(data: string, secret: string): string;
12
+ //# sourceMappingURL=get-packlytics-id.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-packlytics-id.d.ts","sourceRoot":"","sources":["../../src/utils/get-packlytics-id.ts"],"names":[],"mappings":"AA4BA;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,UAO3D"}
@@ -0,0 +1,36 @@
1
+ import crypto from "crypto";
2
+ function generateUUIDFromHash(hash) {
3
+ const crypto = require("crypto");
4
+ const bytes = crypto.createHash("sha1").update(hash).digest();
5
+ bytes[6] = (bytes[6] & 0x0f) | 0x50; // Set version to 5 (version 5 UUID)
6
+ bytes[8] = (bytes[8] & 0x3f) | 0x80; // Set variant to RFC 4122
7
+ const uuid = bytes.toString("hex", 0, 16);
8
+ return [
9
+ uuid.substring(0, 8),
10
+ uuid.substring(8, 12),
11
+ uuid.substring(12, 16),
12
+ uuid.substring(16, 20),
13
+ uuid.substring(20),
14
+ ].join("-");
15
+ }
16
+ function createHash(data, algorithm = "sha256") {
17
+ const hash = crypto.createHash(algorithm);
18
+ hash.update(data);
19
+ return generateUUIDFromHash(hash.digest("hex"));
20
+ }
21
+ /**
22
+ * Generates a UUID from the user data, such as user-agent and IP Address + Salt
23
+ * The salt is generated on the currante date + a Secret from the StoreFront,
24
+ * So this UUID will be regenerated every day.
25
+ *
26
+ * We can never use this id to trace back users for GDPR compliance.
27
+ *
28
+ * @param data
29
+ * @param secret
30
+ */
31
+ export function getPacklyticsId(data, secret) {
32
+ const currentDate = new Date();
33
+ const formattedDate = currentDate.toLocaleDateString("en-US");
34
+ const salt = createHash(formattedDate + secret);
35
+ return createHash(data + salt);
36
+ }
@@ -0,0 +1,3 @@
1
+ import type { PageViewEvent } from "../packlytics.types";
2
+ export declare const trackPageHit: (storefrontId: string, sessionId: string) => (eventPayload?: PageViewEvent) => Promise<Response | undefined>;
3
+ //# sourceMappingURL=page-hit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page-hit.d.ts","sourceRoot":"","sources":["../../src/utils/page-hit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAGzD,eAAO,MAAM,YAAY,iBAAkB,MAAM,aAAa,MAAM,qBAC5C,aAAa,kCAGpC,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { sendEvent } from "./send-event";
2
+ export const trackPageHit = (storefrontId, sessionId) => {
3
+ return (eventPayload = {}) => {
4
+ return sendEvent(storefrontId, sessionId)("page_hit", eventPayload);
5
+ };
6
+ };
@@ -0,0 +1,2 @@
1
+ export declare const sanitizePayload: (data: any) => string;
2
+ //# sourceMappingURL=sanatize-payload.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanatize-payload.d.ts","sourceRoot":"","sources":["../../src/utils/sanatize-payload.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,eAAe,SAAU,GAAG,WAiCxC,CAAC"}
@@ -0,0 +1,30 @@
1
+ // Generic list of potential sensitive payload data
2
+ export const sanitizePayload = (data) => {
3
+ let dataStr = JSON.stringify(data);
4
+ const sensitiveFields = [
5
+ "username",
6
+ "user",
7
+ "user_id",
8
+ "userid",
9
+ "password",
10
+ "pass",
11
+ "pin",
12
+ "passcode",
13
+ "token",
14
+ "api_token",
15
+ "email",
16
+ "address",
17
+ "phone",
18
+ "sex",
19
+ "gender",
20
+ "order",
21
+ "order_id",
22
+ "orderid",
23
+ "payment",
24
+ "credit_card",
25
+ ];
26
+ sensitiveFields.forEach((field) => {
27
+ dataStr = dataStr.replaceAll(new RegExp(`("${field}"):(".+?"|\\d+)`, "mgi"), '$1:"********"');
28
+ });
29
+ return dataStr;
30
+ };
@@ -0,0 +1,3 @@
1
+ import type { EventDataPayload } from "../packlytics.types";
2
+ export declare const sendEvent: (storefrontId: string, sessionId: string) => (action: string, eventPayload: EventDataPayload) => Promise<Response | undefined>;
3
+ //# sourceMappingURL=send-event.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"send-event.d.ts","sourceRoot":"","sources":["../../src/utils/send-event.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAa,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAsCvE,eAAO,MAAM,SAAS,iBAAkB,MAAM,aAAa,MAAM,cACzC,MAAM,gBAAgB,gBAAgB,kCA0C7D,CAAC"}
@@ -0,0 +1,61 @@
1
+ import { sanitizePayload } from "./sanatize-payload";
2
+ let metadata = null;
3
+ const getPacklyticsMetadata = async () => {
4
+ if (metadata)
5
+ return;
6
+ try {
7
+ const response = await fetch("https://cdn.packlytics.packdigital.com/metadata.json", {
8
+ headers: {
9
+ "User-Agent": "packlytics-js",
10
+ "Content-Type": "application/json",
11
+ Accept: "application/json",
12
+ },
13
+ });
14
+ if (response.ok) {
15
+ metadata = await response.json();
16
+ }
17
+ else {
18
+ console.error("Error getting Packlytics metadata:", response.statusText);
19
+ }
20
+ }
21
+ catch (error) {
22
+ // @ts-ignore
23
+ console.error("Error getting Packlytics metadata:", error.message);
24
+ }
25
+ };
26
+ export const sendEvent = (storefrontId, sessionId) => {
27
+ return async (action, eventPayload) => {
28
+ const sanitizedEventPayload = sanitizePayload({
29
+ ...eventPayload,
30
+ });
31
+ await getPacklyticsMetadata();
32
+ if (!metadata) {
33
+ console.warn("Pack event not sent: packlytics medatada is missing");
34
+ return;
35
+ }
36
+ // implement localization and add EU
37
+ const analyticsData = metadata["us"] || metadata["default"];
38
+ if (!analyticsData.token) {
39
+ console.warn("Pack event not sent: api token is missing");
40
+ return;
41
+ }
42
+ const dataSourceName = metadata["dataSourceName"] || "analytics_events";
43
+ const endpointUrl = `${analyticsData.endpoint}/${analyticsData.version}/events?name=${dataSourceName}&token=${analyticsData.token}`;
44
+ // qualified event data with payload and session id
45
+ const eventData = {
46
+ timestamp: new Date().toISOString(),
47
+ action,
48
+ version: "1",
49
+ storefront_id: storefrontId || "unknown",
50
+ session_id: sessionId,
51
+ payload: sanitizedEventPayload,
52
+ };
53
+ return fetch(endpointUrl, {
54
+ method: "POST",
55
+ headers: {
56
+ "Content-Type": "application/json",
57
+ },
58
+ body: JSON.stringify(eventData),
59
+ });
60
+ };
61
+ };
@@ -0,0 +1,2 @@
1
+ export declare const timeZoneCountryMap: Record<string, string>;
2
+ //# sourceMappingURL=timezone-country-map.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timezone-country-map.d.ts","sourceRoot":"","sources":["../../src/utils/timezone-country-map.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CA2arD,CAAC"}
@@ -0,0 +1,428 @@
1
+ export const timeZoneCountryMap = {
2
+ // ... (list of time zones and their corresponding country codes)
3
+ "Asia/Barnaul": "RU",
4
+ "Africa/Nouakchott": "MR",
5
+ "Africa/Lusaka": "ZM",
6
+ "Asia/Pyongyang": "KP",
7
+ "Europe/Bratislava": "SK",
8
+ "America/Belize": "BZ",
9
+ "America/Maceio": "BR",
10
+ "Pacific/Chuuk": "FM",
11
+ "Indian/Comoro": "KM",
12
+ "Pacific/Palau": "PW",
13
+ "Asia/Jakarta": "ID",
14
+ "Africa/Windhoek": "NA",
15
+ "America/Chihuahua": "MX",
16
+ "America/Nome": "US",
17
+ "Africa/Mbabane": "SZ",
18
+ "Africa/Porto-Novo": "BJ",
19
+ "Europe/San_Marino": "SM",
20
+ "Pacific/Fakaofo": "TK",
21
+ "America/Denver": "US",
22
+ "Europe/Belgrade": "RS",
23
+ "America/Indiana/Tell_City": "US",
24
+ "America/Fortaleza": "BR",
25
+ "America/Halifax": "CA",
26
+ "Europe/Bucharest": "RO",
27
+ "America/Indiana/Petersburg": "US",
28
+ "Europe/Kirov": "RU",
29
+ "Europe/Athens": "GR",
30
+ "America/Argentina/Ushuaia": "AR",
31
+ "Europe/Monaco": "MC",
32
+ "Europe/Vilnius": "LT",
33
+ "Europe/Copenhagen": "DK",
34
+ "Pacific/Kanton": "KI",
35
+ "America/Caracas": "VE",
36
+ "Asia/Almaty": "KZ",
37
+ "Europe/Paris": "FR",
38
+ "Africa/Blantyre": "MW",
39
+ "Asia/Muscat": "OM",
40
+ "America/North_Dakota/Beulah": "US",
41
+ "America/Matamoros": "MX",
42
+ "Asia/Irkutsk": "RU",
43
+ "America/Costa_Rica": "CR",
44
+ "America/Araguaina": "BR",
45
+ "Atlantic/Canary": "ES",
46
+ "America/Santo_Domingo": "DO",
47
+ "America/Vancouver": "CA",
48
+ "Africa/Addis_Ababa": "ET",
49
+ "Africa/Accra": "GH",
50
+ "Pacific/Kwajalein": "MH",
51
+ "Asia/Baghdad": "IQ",
52
+ "Australia/Adelaide": "AU",
53
+ "Australia/Hobart": "AU",
54
+ "America/Guayaquil": "EC",
55
+ "America/Argentina/Tucuman": "AR",
56
+ "Australia/Lindeman": "AU",
57
+ "America/New_York": "US",
58
+ "Pacific/Fiji": "FJ",
59
+ "America/Antigua": "AG",
60
+ "Africa/Casablanca": "MA",
61
+ "America/Paramaribo": "SR",
62
+ "Africa/Cairo": "EG",
63
+ "America/Cayenne": "GF",
64
+ "America/Detroit": "US",
65
+ "Antarctica/Syowa": "AQ",
66
+ "Africa/Douala": "CM",
67
+ "America/Argentina/La_Rioja": "AR",
68
+ "Africa/Lagos": "NG",
69
+ "America/St_Barthelemy": "BL",
70
+ "Asia/Nicosia": "CY",
71
+ "Asia/Macau": "MO",
72
+ "Europe/Riga": "LV",
73
+ "Asia/Ashgabat": "TM",
74
+ "Indian/Antananarivo": "MG",
75
+ "America/Argentina/San_Juan": "AR",
76
+ "Asia/Aden": "YE",
77
+ "Asia/Tomsk": "RU",
78
+ "America/Asuncion": "PY",
79
+ "Pacific/Bougainville": "PG",
80
+ "Asia/Vientiane": "LA",
81
+ "America/Mazatlan": "MX",
82
+ "Africa/Luanda": "AO",
83
+ "Europe/Oslo": "NO",
84
+ "Africa/Kinshasa": "CD",
85
+ "Europe/Warsaw": "PL",
86
+ "America/Grand_Turk": "TC",
87
+ "Asia/Seoul": "KR",
88
+ "Africa/Tripoli": "LY",
89
+ "America/St_Thomas": "VI",
90
+ "Asia/Kathmandu": "NP",
91
+ "Pacific/Pitcairn": "PN",
92
+ "Pacific/Nauru": "NR",
93
+ "America/Curacao": "CW",
94
+ "Asia/Kabul": "AF",
95
+ "Pacific/Tongatapu": "TO",
96
+ "Europe/Simferopol": "UA",
97
+ "Asia/Ust-Nera": "RU",
98
+ "Africa/Mogadishu": "SO",
99
+ "Indian/Mayotte": "YT",
100
+ "Pacific/Niue": "NU",
101
+ "America/Thunder_Bay": "CA",
102
+ "Atlantic/Azores": "PT",
103
+ "Pacific/Gambier": "PF",
104
+ "Europe/Stockholm": "SE",
105
+ "Africa/Libreville": "GA",
106
+ "America/Punta_Arenas": "CL",
107
+ "America/Guatemala": "GT",
108
+ "America/Noronha": "BR",
109
+ "Europe/Helsinki": "FI",
110
+ "Asia/Gaza": "PS",
111
+ "Pacific/Kosrae": "FM",
112
+ "America/Aruba": "AW",
113
+ "America/Nassau": "BS",
114
+ "Asia/Choibalsan": "MN",
115
+ "America/Winnipeg": "CA",
116
+ "America/Anguilla": "AI",
117
+ "Asia/Thimphu": "BT",
118
+ "Asia/Beirut": "LB",
119
+ "Atlantic/Faroe": "FO",
120
+ "Europe/Berlin": "DE",
121
+ "Europe/Amsterdam": "NL",
122
+ "Pacific/Honolulu": "US",
123
+ "America/Regina": "CA",
124
+ "America/Scoresbysund": "GL",
125
+ "Europe/Vienna": "AT",
126
+ "Europe/Tirane": "AL",
127
+ "Africa/El_Aaiun": "EH",
128
+ "America/Creston": "CA",
129
+ "Asia/Qostanay": "KZ",
130
+ "Asia/Ho_Chi_Minh": "VN",
131
+ "Europe/Samara": "RU",
132
+ "Europe/Rome": "IT",
133
+ "Australia/Eucla": "AU",
134
+ "America/El_Salvador": "SV",
135
+ "America/Chicago": "US",
136
+ "Africa/Abidjan": "CI",
137
+ "Asia/Kamchatka": "RU",
138
+ "Pacific/Tarawa": "KI",
139
+ "America/Santiago": "CL",
140
+ "America/Bahia": "BR",
141
+ "Indian/Christmas": "CX",
142
+ "Asia/Atyrau": "KZ",
143
+ "Asia/Dushanbe": "TJ",
144
+ "Europe/Ulyanovsk": "RU",
145
+ "America/Yellowknife": "CA",
146
+ "America/Recife": "BR",
147
+ "Australia/Sydney": "AU",
148
+ "America/Fort_Nelson": "CA",
149
+ "Pacific/Efate": "VU",
150
+ "Europe/Saratov": "RU",
151
+ "Africa/Banjul": "GM",
152
+ "Asia/Omsk": "RU",
153
+ "Europe/Ljubljana": "SI",
154
+ "Europe/Budapest": "HU",
155
+ "Europe/Astrakhan": "RU",
156
+ "America/Argentina/Buenos_Aires": "AR",
157
+ "Pacific/Chatham": "NZ",
158
+ "America/Argentina/Salta": "AR",
159
+ "Africa/Niamey": "NE",
160
+ "Asia/Pontianak": "ID",
161
+ "Indian/Reunion": "RE",
162
+ "Asia/Hong_Kong": "HK",
163
+ "Antarctica/McMurdo": "AQ",
164
+ "Africa/Malabo": "GQ",
165
+ "America/Los_Angeles": "US",
166
+ "America/Argentina/Cordoba": "AR",
167
+ "Pacific/Pohnpei": "FM",
168
+ "America/Tijuana": "MX",
169
+ "America/Campo_Grande": "BR",
170
+ "America/Dawson_Creek": "CA",
171
+ "Asia/Novosibirsk": "RU",
172
+ "Pacific/Pago_Pago": "AS",
173
+ "Asia/Jerusalem": "IL",
174
+ "Europe/Sarajevo": "BA",
175
+ "Africa/Freetown": "SL",
176
+ "Asia/Yekaterinburg": "RU",
177
+ "America/Juneau": "US",
178
+ "Africa/Ouagadougou": "BF",
179
+ "Africa/Monrovia": "LR",
180
+ "Europe/Kiev": "UA",
181
+ "America/Argentina/San_Luis": "AR",
182
+ "Asia/Tokyo": "JP",
183
+ "Asia/Qatar": "QA",
184
+ "America/La_Paz": "BO",
185
+ "America/Bogota": "CO",
186
+ "America/Thule": "GL",
187
+ "Asia/Manila": "PH",
188
+ "Asia/Hovd": "MN",
189
+ "Asia/Tehran": "IR",
190
+ "Atlantic/Madeira": "PT",
191
+ "America/Metlakatla": "US",
192
+ "Europe/Vatican": "VA",
193
+ "Asia/Bishkek": "KG",
194
+ "Asia/Dili": "TL",
195
+ "Antarctica/Palmer": "AQ",
196
+ "Atlantic/Cape_Verde": "CV",
197
+ "Indian/Chagos": "IO",
198
+ "America/Kentucky/Monticello": "US",
199
+ "Africa/Algiers": "DZ",
200
+ "Africa/Maseru": "LS",
201
+ "Asia/Kuala_Lumpur": "MY",
202
+ "Africa/Khartoum": "SD",
203
+ "America/Argentina/Rio_Gallegos": "AR",
204
+ "America/Blanc-Sablon": "CA",
205
+ "Africa/Maputo": "MZ",
206
+ "America/Tortola": "VG",
207
+ "Atlantic/Bermuda": "BM",
208
+ "America/Argentina/Catamarca": "AR",
209
+ "America/Cayman": "KY",
210
+ "America/Puerto_Rico": "PR",
211
+ "Pacific/Majuro": "MH",
212
+ "Europe/Busingen": "DE",
213
+ "Pacific/Midway": "UM",
214
+ "Indian/Cocos": "CC",
215
+ "Asia/Singapore": "SG",
216
+ "America/Boise": "US",
217
+ "America/Nuuk": "GL",
218
+ "America/Goose_Bay": "CA",
219
+ "Australia/Broken_Hill": "AU",
220
+ "Africa/Dar_es_Salaam": "TZ",
221
+ "Africa/Asmara": "ER",
222
+ "Asia/Samarkand": "UZ",
223
+ "Asia/Tbilisi": "GE",
224
+ "America/Argentina/Jujuy": "AR",
225
+ "America/Indiana/Winamac": "US",
226
+ "America/Porto_Velho": "BR",
227
+ "Asia/Magadan": "RU",
228
+ "Europe/Zaporozhye": "UA",
229
+ "Antarctica/Casey": "AQ",
230
+ "Asia/Shanghai": "CN",
231
+ "Pacific/Norfolk": "NF",
232
+ "Europe/Guernsey": "GG",
233
+ "Australia/Brisbane": "AU",
234
+ "Antarctica/DumontDUrville": "AQ",
235
+ "America/Havana": "CU",
236
+ "America/Atikokan": "CA",
237
+ "America/Mexico_City": "MX",
238
+ "America/Rankin_Inlet": "CA",
239
+ "America/Cuiaba": "BR",
240
+ "America/Resolute": "CA",
241
+ "Africa/Ceuta": "ES",
242
+ "Arctic/Longyearbyen": "SJ",
243
+ "Pacific/Guam": "GU",
244
+ "Asia/Damascus": "SY",
245
+ "Asia/Colombo": "LK",
246
+ "Asia/Yerevan": "AM",
247
+ "America/Montserrat": "MS",
248
+ "America/Belem": "BR",
249
+ "Europe/Kaliningrad": "RU",
250
+ "Atlantic/South_Georgia": "GS",
251
+ "Asia/Tashkent": "UZ",
252
+ "Asia/Kolkata": "IN",
253
+ "America/St_Johns": "CA",
254
+ "Asia/Srednekolymsk": "RU",
255
+ "Asia/Yakutsk": "RU",
256
+ "Europe/Prague": "CZ",
257
+ "Africa/Djibouti": "DJ",
258
+ "Asia/Dubai": "AE",
259
+ "Europe/Uzhgorod": "UA",
260
+ "America/Edmonton": "CA",
261
+ "Asia/Famagusta": "CY",
262
+ "America/Indiana/Knox": "US",
263
+ "Asia/Hebron": "PS",
264
+ "Asia/Taipei": "TW",
265
+ "Europe/London": "GB",
266
+ "Africa/Dakar": "SN",
267
+ "Australia/Darwin": "AU",
268
+ "America/Glace_Bay": "CA",
269
+ "Antarctica/Vostok": "AQ",
270
+ "America/Indiana/Vincennes": "US",
271
+ "America/Nipigon": "CA",
272
+ "Asia/Kuwait": "KW",
273
+ "Pacific/Guadalcanal": "SB",
274
+ "America/Toronto": "CA",
275
+ "Africa/Gaborone": "BW",
276
+ "Africa/Bujumbura": "BI",
277
+ "Africa/Lubumbashi": "CD",
278
+ "America/Merida": "MX",
279
+ "America/Marigot": "MF",
280
+ "Europe/Zagreb": "HR",
281
+ "Pacific/Easter": "CL",
282
+ "America/Santarem": "BR",
283
+ "Pacific/Noumea": "NC",
284
+ "America/Sitka": "US",
285
+ "Atlantic/Stanley": "FK",
286
+ "Pacific/Funafuti": "TV",
287
+ "America/Iqaluit": "CA",
288
+ "America/Rainy_River": "CA",
289
+ "America/Anchorage": "US",
290
+ "America/Lima": "PE",
291
+ "Asia/Baku": "AZ",
292
+ "America/Indiana/Vevay": "US",
293
+ "Asia/Ulaanbaatar": "MN",
294
+ "America/Managua": "NI",
295
+ "Asia/Krasnoyarsk": "RU",
296
+ "Asia/Qyzylorda": "KZ",
297
+ "America/Eirunepe": "BR",
298
+ "Europe/Podgorica": "ME",
299
+ "Europe/Chisinau": "MD",
300
+ "Europe/Mariehamn": "AX",
301
+ "Europe/Volgograd": "RU",
302
+ "Africa/Nairobi": "KE",
303
+ "Europe/Isle_of_Man": "IM",
304
+ "America/Menominee": "US",
305
+ "Africa/Harare": "ZW",
306
+ "Asia/Anadyr": "RU",
307
+ "America/Moncton": "CA",
308
+ "Indian/Maldives": "MV",
309
+ "America/Whitehorse": "CA",
310
+ "Antarctica/Mawson": "AQ",
311
+ "Europe/Madrid": "ES",
312
+ "America/Argentina/Mendoza": "AR",
313
+ "America/Manaus": "BR",
314
+ "Africa/Bangui": "CF",
315
+ "Indian/Mauritius": "MU",
316
+ "Africa/Tunis": "TN",
317
+ "Australia/Lord_Howe": "AU",
318
+ "America/Kentucky/Louisville": "US",
319
+ "America/North_Dakota/Center": "US",
320
+ "Asia/Novokuznetsk": "RU",
321
+ "Asia/Makassar": "ID",
322
+ "America/Port_of_Spain": "TT",
323
+ "America/Bahia_Banderas": "MX",
324
+ "Pacific/Auckland": "NZ",
325
+ "America/Sao_Paulo": "BR",
326
+ "Asia/Dhaka": "BD",
327
+ "America/Pangnirtung": "CA",
328
+ "Europe/Dublin": "IE",
329
+ "Asia/Brunei": "BN",
330
+ "Africa/Brazzaville": "CG",
331
+ "America/Montevideo": "UY",
332
+ "America/Jamaica": "JM",
333
+ "America/Indiana/Indianapolis": "US",
334
+ "America/Kralendijk": "BQ",
335
+ "Europe/Gibraltar": "GI",
336
+ "Pacific/Marquesas": "PF",
337
+ "Pacific/Apia": "WS",
338
+ "Europe/Jersey": "JE",
339
+ "America/Phoenix": "US",
340
+ "Africa/Ndjamena": "TD",
341
+ "Asia/Karachi": "PK",
342
+ "Africa/Kampala": "UG",
343
+ "Asia/Sakhalin": "RU",
344
+ "America/Martinique": "MQ",
345
+ "Europe/Moscow": "RU",
346
+ "Africa/Conakry": "GN",
347
+ "America/Barbados": "BB",
348
+ "Africa/Lome": "TG",
349
+ "America/Ojinaga": "MX",
350
+ "America/Tegucigalpa": "HN",
351
+ "Asia/Bangkok": "TH",
352
+ "Africa/Johannesburg": "ZA",
353
+ "Europe/Vaduz": "LI",
354
+ "Africa/Sao_Tome": "ST",
355
+ "America/Cambridge_Bay": "CA",
356
+ "America/Lower_Princes": "SX",
357
+ "America/Miquelon": "PM",
358
+ "America/St_Kitts": "KN",
359
+ "Australia/Melbourne": "AU",
360
+ "Europe/Minsk": "BY",
361
+ "Asia/Vladivostok": "RU",
362
+ "Europe/Sofia": "BG",
363
+ "Antarctica/Davis": "AQ",
364
+ "Pacific/Galapagos": "EC",
365
+ "America/North_Dakota/New_Salem": "US",
366
+ "Asia/Amman": "JO",
367
+ "Pacific/Wallis": "WF",
368
+ "America/Hermosillo": "MX",
369
+ "Pacific/Kiritimati": "KI",
370
+ "Antarctica/Macquarie": "AU",
371
+ "America/Guyana": "GY",
372
+ "Asia/Riyadh": "SA",
373
+ "Pacific/Tahiti": "PF",
374
+ "America/St_Vincent": "VC",
375
+ "America/Cancun": "MX",
376
+ "America/Grenada": "GD",
377
+ "Pacific/Wake": "UM",
378
+ "America/Dawson": "CA",
379
+ "Europe/Brussels": "BE",
380
+ "Indian/Kerguelen": "TF",
381
+ "America/Yakutat": "US",
382
+ "Indian/Mahe": "SC",
383
+ "Atlantic/Reykjavik": "IS",
384
+ "America/Panama": "PA",
385
+ "America/Guadeloupe": "GP",
386
+ "Europe/Malta": "MT",
387
+ "Antarctica/Troll": "AQ",
388
+ "Asia/Jayapura": "ID",
389
+ "Asia/Bahrain": "BH",
390
+ "Asia/Chita": "RU",
391
+ "Europe/Tallinn": "EE",
392
+ "Asia/Khandyga": "RU",
393
+ "America/Rio_Branco": "BR",
394
+ "Atlantic/St_Helena": "SH",
395
+ "Africa/Juba": "SS",
396
+ "America/Adak": "US",
397
+ "Pacific/Saipan": "MP",
398
+ "America/St_Lucia": "LC",
399
+ "America/Inuvik": "CA",
400
+ "Europe/Luxembourg": "LU",
401
+ "Africa/Bissau": "GW",
402
+ "Asia/Oral": "KZ",
403
+ "America/Boa_Vista": "BR",
404
+ "Europe/Skopje": "MK",
405
+ "America/Port-au-Prince": "HT",
406
+ "Pacific/Port_Moresby": "PG",
407
+ "Europe/Andorra": "AD",
408
+ "America/Indiana/Marengo": "US",
409
+ "Africa/Kigali": "RW",
410
+ "Africa/Bamako": "ML",
411
+ "America/Dominica": "DM",
412
+ "Asia/Aqtobe": "KZ",
413
+ "Europe/Istanbul": "TR",
414
+ "Pacific/Rarotonga": "CK",
415
+ "America/Danmarkshavn": "GL",
416
+ "Europe/Zurich": "CH",
417
+ "Asia/Yangon": "MM",
418
+ "America/Monterrey": "MX",
419
+ "Europe/Lisbon": "PT",
420
+ "Asia/Kuching": "MY",
421
+ "Antarctica/Rothera": "AQ",
422
+ "Australia/Perth": "AU",
423
+ "Asia/Phnom_Penh": "KH",
424
+ "America/Swift_Current": "CA",
425
+ "Asia/Aqtau": "KZ",
426
+ "Asia/Urumqi": "CN",
427
+ "Asia/Calcutta": "IN",
428
+ };
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "@pack/packlytics",
3
+ "description": "Packlytics",
4
+ "version": "0.0.1-ab-beta.2.0",
5
+ "exports": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
7
+ "engines": {
8
+ "node": ">=16"
9
+ },
10
+ "publishConfig": {
11
+ "access": "public"
12
+ },
13
+ "scripts": {
14
+ "clean": "npx rimraf dist",
15
+ "build": "npx tsc",
16
+ "test": "",
17
+ "test:watch": "npx vitest"
18
+ },
19
+ "author": "Pack",
20
+ "license": "MIT",
21
+ "files": [
22
+ "dist"
23
+ ],
24
+ "dependencies": {
25
+ "@remix-run/react": "^2.7.2",
26
+ "intl-parse-accept-language": "^1.0.0",
27
+ "is-ip": "^5.0.1",
28
+ "ua-parser-js": "^1.0.37"
29
+ },
30
+ "devDependencies": {
31
+ "@types/node": "^20.11.17",
32
+ "@types/ua-parser-js": "^0.7.39"
33
+ },
34
+ "peerDependencies": {
35
+ "react": "^18.0.0"
36
+ }
37
+ }