@pack/packlytics 0.1.0-ab-beta.0 → 1.0.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.
- package/dist/packlytics.d.ts +1 -2
- package/dist/packlytics.d.ts.map +1 -1
- package/dist/packlytics.js +19 -8
- package/dist/packlytics.types.d.ts +0 -25
- package/dist/packlytics.types.d.ts.map +1 -1
- package/dist/utils/get-client-location.d.ts +2 -0
- package/dist/utils/get-client-location.d.ts.map +1 -0
- package/dist/utils/get-client-location.js +4 -0
- package/dist/utils/get-packlytics-id.d.ts.map +1 -1
- package/dist/utils/get-packlytics-id.js +100 -18
- package/dist/utils/send-event.js +2 -2
- package/package.json +1 -1
package/dist/packlytics.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
export declare function usePacklytics(request: Request, pack: Pack, params: {
|
|
1
|
+
export declare function packlytics(request: Request, session: any, params: {
|
|
3
2
|
storeFrontId: string;
|
|
4
3
|
sessionSecret: string;
|
|
5
4
|
}): Promise<Response | undefined>;
|
package/dist/packlytics.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"packlytics.d.ts","sourceRoot":"","sources":["../src/packlytics.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"packlytics.d.ts","sourceRoot":"","sources":["../src/packlytics.ts"],"names":[],"mappings":"AAOA,wBAAsB,UAAU,CAC9B,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,GAAG,EACZ,MAAM,EAAE;IACN,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;CACvB,iCAiDF"}
|
package/dist/packlytics.js
CHANGED
|
@@ -1,16 +1,26 @@
|
|
|
1
|
-
import { getClientIPAddress } from "./utils/get-client-ip-address";
|
|
2
1
|
import { getPacklyticsId } from "./utils/get-packlytics-id";
|
|
3
2
|
import { getClientLocales } from "./utils/get-client-locales";
|
|
4
3
|
import { trackPageHit } from "./utils/page-hit";
|
|
5
4
|
import { getDevice } from "./utils/get-client-device";
|
|
6
|
-
|
|
5
|
+
import { getStorefrontHeaders } from "@shopify/remix-oxygen";
|
|
6
|
+
import { getClientLocation } from "./utils/get-client-location";
|
|
7
|
+
export async function packlytics(request, session, params) {
|
|
8
|
+
if (process.env.NODE_ENV === "development") {
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
// Preview enabled
|
|
12
|
+
if (!!session.get("previewEnabled")) {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
7
15
|
const url = new URL(request.url);
|
|
8
|
-
const ipaddress =
|
|
16
|
+
const ipaddress = getStorefrontHeaders(request)["buyerIp"] || "";
|
|
9
17
|
const dataToHash = `${request.headers.get("user-agent")}${ipaddress}${url.hostname}`;
|
|
10
18
|
const packlyticsId = getPacklyticsId(dataToHash, params.sessionSecret);
|
|
11
|
-
const testSession =
|
|
19
|
+
const testSession = session.get("test");
|
|
20
|
+
const locale = getClientLocales(request) || ["en-US"];
|
|
21
|
+
const location = getClientLocation(locale[0]);
|
|
12
22
|
return trackPageHit(params.storeFrontId, packlyticsId)({
|
|
13
|
-
"pack-session-id":
|
|
23
|
+
"pack-session-id": session.id, // This session ID is saved on the __pack cookie
|
|
14
24
|
"user-agent": request.headers.get("user-agent") || "",
|
|
15
25
|
pathname: url.pathname,
|
|
16
26
|
query: url.search,
|
|
@@ -18,15 +28,16 @@ export async function usePacklytics(request, pack, params) {
|
|
|
18
28
|
referrer: request.referrer,
|
|
19
29
|
ipaddress: ipaddress,
|
|
20
30
|
language: getClientLocales(request) || "",
|
|
21
|
-
locale:
|
|
31
|
+
locale: locale[0],
|
|
32
|
+
location: location,
|
|
22
33
|
connection: request.headers.get("connection") || "",
|
|
23
34
|
href: request.url,
|
|
24
35
|
...getDevice(request.headers.get("user-agent") || ""),
|
|
25
36
|
test: {
|
|
26
37
|
"test-id": testSession?.data?.id || "",
|
|
27
38
|
"test-handle": testSession?.data?.handle || "",
|
|
28
|
-
"test-variant-id": testSession?.data?.
|
|
29
|
-
"test-variant-handle": testSession?.data?.
|
|
39
|
+
"test-variant-id": testSession?.data?.testVariant?.id || "",
|
|
40
|
+
"test-variant-handle": testSession?.data?.testVariant?.handle || "",
|
|
30
41
|
},
|
|
31
42
|
});
|
|
32
43
|
}
|
|
@@ -10,34 +10,9 @@ interface JSONArray extends Array<JSONValue> {
|
|
|
10
10
|
interface JSONObject {
|
|
11
11
|
[x: string]: JSONValue;
|
|
12
12
|
}
|
|
13
|
-
export interface Pack {
|
|
14
|
-
session: any;
|
|
15
|
-
}
|
|
16
|
-
export interface Test {
|
|
17
|
-
id: string;
|
|
18
|
-
handle: string;
|
|
19
|
-
TestVariant: {
|
|
20
|
-
id: string;
|
|
21
|
-
handle: string;
|
|
22
|
-
};
|
|
23
|
-
}
|
|
24
13
|
export type PackData = {
|
|
25
14
|
version: string;
|
|
26
15
|
};
|
|
27
|
-
export type BrowserData = {
|
|
28
|
-
"user-agent": string;
|
|
29
|
-
pathname: string;
|
|
30
|
-
query: string;
|
|
31
|
-
screen: string;
|
|
32
|
-
referrer: string;
|
|
33
|
-
hostname: string;
|
|
34
|
-
language: string;
|
|
35
|
-
locale: string;
|
|
36
|
-
location: string;
|
|
37
|
-
connection: string;
|
|
38
|
-
deviceCategory: string;
|
|
39
|
-
href: string;
|
|
40
|
-
};
|
|
41
16
|
export type EventDataPayload = JSONObject;
|
|
42
17
|
export type EventData = PackData & {
|
|
43
18
|
timestamp: string;
|
|
@@ -1 +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,
|
|
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
|
+
{"version":3,"file":"get-client-location.d.ts","sourceRoot":"","sources":["../../src/utils/get-client-location.ts"],"names":[],"mappings":"AAAA,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,UAI/C"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-packlytics-id.d.ts","sourceRoot":"","sources":["../../src/utils/get-packlytics-id.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"get-packlytics-id.d.ts","sourceRoot":"","sources":["../../src/utils/get-packlytics-id.ts"],"names":[],"mappings":"AAuHA;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,UAO3D"}
|
|
@@ -1,23 +1,105 @@
|
|
|
1
|
-
|
|
2
|
-
function
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const
|
|
1
|
+
function sha256(ascii) {
|
|
2
|
+
function rightRotate(value, amount) {
|
|
3
|
+
return (value >>> amount) | (value << (32 - amount));
|
|
4
|
+
}
|
|
5
|
+
const mathPow = Math.pow;
|
|
6
|
+
const maxWord = mathPow(2, 32);
|
|
7
|
+
const lengthProperty = "length";
|
|
8
|
+
let i, j; // Used as a counter across the whole file
|
|
9
|
+
let result = "";
|
|
10
|
+
const words = [];
|
|
11
|
+
const asciiBitLength = ascii[lengthProperty] * 8;
|
|
12
|
+
//* caching results is optional - remove/add slash from front of this line to toggle
|
|
13
|
+
// Initial hash value: first 32 bits of the fractional parts of the square roots of the first 8 primes
|
|
14
|
+
// (we actually calculate the first 64, but extra values are just ignored)
|
|
15
|
+
// @ts-ignore
|
|
16
|
+
let hash = (sha256.h = sha256.h || []);
|
|
17
|
+
// Round constants: first 32 bits of the fractional parts of the cube roots of the first 64 primes
|
|
18
|
+
// @ts-ignore
|
|
19
|
+
const k = (sha256.k = sha256.k || []);
|
|
20
|
+
let primeCounter = k[lengthProperty];
|
|
21
|
+
/*/
|
|
22
|
+
var hash = [], k = [];
|
|
23
|
+
var primeCounter = 0;
|
|
24
|
+
//*/
|
|
25
|
+
const isComposite = {};
|
|
26
|
+
for (let candidate = 2; primeCounter < 64; candidate++) {
|
|
27
|
+
// @ts-ignore
|
|
28
|
+
if (!isComposite[candidate]) {
|
|
29
|
+
for (i = 0; i < 313; i += candidate) {
|
|
30
|
+
// @ts-ignore
|
|
31
|
+
isComposite[i] = candidate;
|
|
32
|
+
}
|
|
33
|
+
hash[primeCounter] = (mathPow(candidate, 0.5) * maxWord) | 0;
|
|
34
|
+
k[primeCounter++] = (mathPow(candidate, 1 / 3) * maxWord) | 0;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
ascii += "\x80"; // Append Ƈ' bit (plus zero padding)
|
|
38
|
+
while ((ascii[lengthProperty] % 64) - 56)
|
|
39
|
+
ascii += "\x00"; // More zero padding
|
|
40
|
+
for (i = 0; i < ascii[lengthProperty]; i++) {
|
|
41
|
+
j = ascii.charCodeAt(i);
|
|
42
|
+
if (j >> 8)
|
|
43
|
+
return; // ASCII check: only accept characters in range 0-255
|
|
44
|
+
words[i >> 2] |= j << (((3 - i) % 4) * 8);
|
|
45
|
+
}
|
|
46
|
+
words[words[lengthProperty]] = (asciiBitLength / maxWord) | 0;
|
|
47
|
+
words[words[lengthProperty]] = asciiBitLength;
|
|
48
|
+
// process each chunk
|
|
49
|
+
for (j = 0; j < words[lengthProperty];) {
|
|
50
|
+
const w = words.slice(j, (j += 16)); // The message is expanded into 64 words as part of the iteration
|
|
51
|
+
const oldHash = hash;
|
|
52
|
+
// This is now the undefinedworking hash", often labelled as variables a...g
|
|
53
|
+
// (we have to truncate as well, otherwise extra entries at the end accumulate
|
|
54
|
+
hash = hash.slice(0, 8);
|
|
55
|
+
for (i = 0; i < 64; i++) {
|
|
56
|
+
const i2 = i + j;
|
|
57
|
+
// Expand the message into 64 words
|
|
58
|
+
// Used below if
|
|
59
|
+
const w15 = w[i - 15], w2 = w[i - 2];
|
|
60
|
+
// Iterate
|
|
61
|
+
const a = hash[0], e = hash[4];
|
|
62
|
+
const temp1 = hash[7] +
|
|
63
|
+
(rightRotate(e, 6) ^ rightRotate(e, 11) ^ rightRotate(e, 25)) + // S1
|
|
64
|
+
((e & hash[5]) ^ (~e & hash[6])) + // ch
|
|
65
|
+
k[i] +
|
|
66
|
+
// Expand the message schedule if needed
|
|
67
|
+
(w[i] =
|
|
68
|
+
i < 16
|
|
69
|
+
? w[i]
|
|
70
|
+
: (w[i - 16] +
|
|
71
|
+
(rightRotate(w15, 7) ^ rightRotate(w15, 18) ^ (w15 >>> 3)) + // s0
|
|
72
|
+
w[i - 7] +
|
|
73
|
+
(rightRotate(w2, 17) ^ rightRotate(w2, 19) ^ (w2 >>> 10))) | // s1
|
|
74
|
+
0);
|
|
75
|
+
// This is only used once, so *could* be moved below, but it only saves 4 bytes and makes things unreadble
|
|
76
|
+
const temp2 = (rightRotate(a, 2) ^ rightRotate(a, 13) ^ rightRotate(a, 22)) + // S0
|
|
77
|
+
((a & hash[1]) ^ (a & hash[2]) ^ (hash[1] & hash[2])); // maj
|
|
78
|
+
hash = [(temp1 + temp2) | 0].concat(hash); // We don't bother trimming off the extra ones, they're harmless as long as we're truncating when we do the slice()
|
|
79
|
+
hash[4] = (hash[4] + temp1) | 0;
|
|
80
|
+
}
|
|
81
|
+
for (i = 0; i < 8; i++) {
|
|
82
|
+
hash[i] = (hash[i] + oldHash[i]) | 0;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
for (i = 0; i < 8; i++) {
|
|
86
|
+
for (j = 3; j + 1; j--) {
|
|
87
|
+
const b = (hash[i] >> (j * 8)) & 255;
|
|
88
|
+
result += (b < 16 ? 0 : "") + b.toString(16);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return result;
|
|
92
|
+
}
|
|
93
|
+
function createHash(data) {
|
|
94
|
+
const hash = sha256(data);
|
|
8
95
|
return [
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
96
|
+
hash?.substring(0, 8),
|
|
97
|
+
hash?.substring(8, 12),
|
|
98
|
+
hash?.substring(12, 16),
|
|
99
|
+
hash?.substring(16, 20),
|
|
100
|
+
hash?.substring(20, 32),
|
|
14
101
|
].join("-");
|
|
15
102
|
}
|
|
16
|
-
function createHash(data, algorithm = "sha256") {
|
|
17
|
-
const hash = crypto.createHash(algorithm);
|
|
18
|
-
hash.update(data);
|
|
19
|
-
return generateUUIDFromHash(hash.digest("hex"));
|
|
20
|
-
}
|
|
21
103
|
/**
|
|
22
104
|
* Generates a UUID from the user data, such as user-agent and IP Address + Salt
|
|
23
105
|
* The salt is generated on the currante date + a Secret from the StoreFront,
|
|
@@ -31,6 +113,6 @@ function createHash(data, algorithm = "sha256") {
|
|
|
31
113
|
export function getPacklyticsId(data, secret) {
|
|
32
114
|
const currentDate = new Date();
|
|
33
115
|
const formattedDate = currentDate.toLocaleDateString("en-US");
|
|
34
|
-
const salt =
|
|
116
|
+
const salt = sha256(formattedDate + secret);
|
|
35
117
|
return createHash(data + salt);
|
|
36
118
|
}
|
package/dist/utils/send-event.js
CHANGED
|
@@ -15,12 +15,12 @@ const getPacklyticsMetadata = async () => {
|
|
|
15
15
|
metadata = await response.json();
|
|
16
16
|
}
|
|
17
17
|
else {
|
|
18
|
-
console.error("Error
|
|
18
|
+
console.error("Error getting Packlytics metadata:", response.statusText);
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
catch (error) {
|
|
22
22
|
// @ts-ignore
|
|
23
|
-
console.error("Error
|
|
23
|
+
console.error("Error getting Packlytics metadata:", error.message);
|
|
24
24
|
}
|
|
25
25
|
};
|
|
26
26
|
export const sendEvent = (storefrontId, sessionId) => {
|