luchy 1.1.0 → 1.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.
- package/README.md +12 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +24 -1
- package/dist/script/luchy.js +25 -1
- package/dist/script/luchy.js.br +0 -0
- package/dist/script/luchy.js.gz +0 -0
- package/dist/script/luchy.min.js +25 -1
- package/dist/script/luchy.min.js.br +0 -0
- package/dist/script/luchy.min.js.gz +0 -0
- package/dist/utm.d.ts +6 -0
- package/dist/utm.d.ts.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -123,6 +123,15 @@ window.luchy.reset();
|
|
|
123
123
|
`identify`/`reset` write through to the script tag's `data-identity` /
|
|
124
124
|
`data-props`, so the tag stays the single source of truth.
|
|
125
125
|
|
|
126
|
+
### UTM attribution
|
|
127
|
+
|
|
128
|
+
Every pageview reads `utm_source`, `utm_medium`, `utm_campaign`, `utm_term`
|
|
129
|
+
and `utm_content` from `location.search` and adds the present ones to its
|
|
130
|
+
payload (trimmed, at most 200 characters). Nothing else from the query string
|
|
131
|
+
is sent, and a key in the pageview's own `payload` wins over the URL. Ingest
|
|
132
|
+
keeps the first `utm_source` / `utm_medium` / `utm_campaign` of a session as
|
|
133
|
+
its attribution.
|
|
134
|
+
|
|
126
135
|
## Identity
|
|
127
136
|
|
|
128
137
|
Luchy ties hits to your users only when your server vouches for them. An
|
|
@@ -218,6 +227,9 @@ await luchy.pageview({ pathname: '/pricing', payload: { plan: 'pro' } });
|
|
|
218
227
|
is the server.
|
|
219
228
|
- Nothing ever rejects — analytics must not break the request it is
|
|
220
229
|
describing. Pass `onError` if you want failures in your logs.
|
|
230
|
+
- UTM attribution is not read from any URL here: pass the same keys
|
|
231
|
+
(`utm_source`, `utm_medium`, `utm_campaign`, `utm_term`, `utm_content`) in
|
|
232
|
+
`payload` and the session is attributed exactly as for the browser script.
|
|
221
233
|
|
|
222
234
|
## API client (`luchy/api`)
|
|
223
235
|
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,YAAY,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEnD,0EAA0E;AAC1E,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;AAEnE,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,sEAAsE;IACtE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,2DAA2D;IAC3D,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,aAAa,CAAC,IAAI,CAAC,EAAE;QACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,OAAO,CAAC,EAAE,UAAU,CAAC;KACtB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClB,UAAU,CACR,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,UAAU,EACpB,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAC1B,OAAO,CAAC,IAAI,CAAC,CAAC;IACjB;;;;OAIG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;IAClD,0DAA0D;IAC1D,KAAK,IAAI,IAAI,CAAC;IACd,UAAU,CAAC,OAAO,EAAE,mBAAmB,GAAG,IAAI,CAAC;CAChD,CAAC;AAgBF;;GAEG;AACH,wBAAgB,KAAK,CAAC,OAAO,EAAE,gBAAgB,GAAG,YAAY,CAka7D"}
|
package/dist/index.js
CHANGED
|
@@ -21,6 +21,24 @@ function collectBrowserData() {
|
|
|
21
21
|
language: navigator.language || navigator.languages?.[0] || "en"
|
|
22
22
|
};
|
|
23
23
|
}
|
|
24
|
+
const UTM_KEYS = [
|
|
25
|
+
"utm_source",
|
|
26
|
+
"utm_medium",
|
|
27
|
+
"utm_campaign",
|
|
28
|
+
"utm_term",
|
|
29
|
+
"utm_content"
|
|
30
|
+
];
|
|
31
|
+
const MAX_LENGTH = 200;
|
|
32
|
+
function utmParams(search) {
|
|
33
|
+
const params = new URLSearchParams(search);
|
|
34
|
+
const utm = {};
|
|
35
|
+
for (const key of UTM_KEYS) {
|
|
36
|
+
const value = params.get(key)?.trim().slice(0, MAX_LENGTH);
|
|
37
|
+
if (!value) continue;
|
|
38
|
+
utm[key] = value;
|
|
39
|
+
}
|
|
40
|
+
return utm;
|
|
41
|
+
}
|
|
24
42
|
function parseProps(raw) {
|
|
25
43
|
if (!raw) return void 0;
|
|
26
44
|
try {
|
|
@@ -73,6 +91,11 @@ function luchy(options) {
|
|
|
73
91
|
if (!global) return payload;
|
|
74
92
|
return { ...global, ...payload };
|
|
75
93
|
}
|
|
94
|
+
function withUtm(payload) {
|
|
95
|
+
const utm = utmParams(location.search || "");
|
|
96
|
+
if (Object.keys(utm).length === 0) return payload;
|
|
97
|
+
return { ...utm, ...payload };
|
|
98
|
+
}
|
|
76
99
|
const shouldTrack = () => {
|
|
77
100
|
if (trackLocalhost) return true;
|
|
78
101
|
return location.hostname !== "localhost" && location.hostname !== "127.0.0.1";
|
|
@@ -88,7 +111,7 @@ function luchy(options) {
|
|
|
88
111
|
data: {
|
|
89
112
|
pathname,
|
|
90
113
|
referrer,
|
|
91
|
-
payload: withProps(data?.payload),
|
|
114
|
+
payload: withProps(withUtm(data?.payload)),
|
|
92
115
|
identity: currentIdentity(),
|
|
93
116
|
...browserData
|
|
94
117
|
}
|
package/dist/script/luchy.js
CHANGED
|
@@ -62,6 +62,25 @@ var __async = (__this, __arguments, generator) => {
|
|
|
62
62
|
language: navigator.language || ((_a = navigator.languages) == null ? void 0 : _a[0]) || "en"
|
|
63
63
|
};
|
|
64
64
|
}
|
|
65
|
+
const UTM_KEYS = [
|
|
66
|
+
"utm_source",
|
|
67
|
+
"utm_medium",
|
|
68
|
+
"utm_campaign",
|
|
69
|
+
"utm_term",
|
|
70
|
+
"utm_content"
|
|
71
|
+
];
|
|
72
|
+
const MAX_LENGTH = 200;
|
|
73
|
+
function utmParams(search) {
|
|
74
|
+
var _a;
|
|
75
|
+
const params = new URLSearchParams(search);
|
|
76
|
+
const utm = {};
|
|
77
|
+
for (const key of UTM_KEYS) {
|
|
78
|
+
const value = (_a = params.get(key)) == null ? void 0 : _a.trim().slice(0, MAX_LENGTH);
|
|
79
|
+
if (!value) continue;
|
|
80
|
+
utm[key] = value;
|
|
81
|
+
}
|
|
82
|
+
return utm;
|
|
83
|
+
}
|
|
65
84
|
function parseProps(raw) {
|
|
66
85
|
if (!raw) return void 0;
|
|
67
86
|
try {
|
|
@@ -114,6 +133,11 @@ var __async = (__this, __arguments, generator) => {
|
|
|
114
133
|
if (!global) return payload;
|
|
115
134
|
return __spreadValues(__spreadValues({}, global), payload);
|
|
116
135
|
}
|
|
136
|
+
function withUtm(payload) {
|
|
137
|
+
const utm = utmParams(location.search || "");
|
|
138
|
+
if (Object.keys(utm).length === 0) return payload;
|
|
139
|
+
return __spreadValues(__spreadValues({}, utm), payload);
|
|
140
|
+
}
|
|
117
141
|
const shouldTrack = () => {
|
|
118
142
|
if (trackLocalhost) return true;
|
|
119
143
|
return location.hostname !== "localhost" && location.hostname !== "127.0.0.1";
|
|
@@ -130,7 +154,7 @@ var __async = (__this, __arguments, generator) => {
|
|
|
130
154
|
data: __spreadValues({
|
|
131
155
|
pathname,
|
|
132
156
|
referrer,
|
|
133
|
-
payload: withProps(data == null ? void 0 : data.payload),
|
|
157
|
+
payload: withProps(withUtm(data == null ? void 0 : data.payload)),
|
|
134
158
|
identity: currentIdentity()
|
|
135
159
|
}, browserData)
|
|
136
160
|
});
|
package/dist/script/luchy.js.br
CHANGED
|
Binary file
|
package/dist/script/luchy.js.gz
CHANGED
|
Binary file
|
package/dist/script/luchy.min.js
CHANGED
|
@@ -62,6 +62,25 @@ var __async = (__this, __arguments, generator) => {
|
|
|
62
62
|
language: navigator.language || ((_a = navigator.languages) == null ? void 0 : _a[0]) || "en"
|
|
63
63
|
};
|
|
64
64
|
}
|
|
65
|
+
const UTM_KEYS = [
|
|
66
|
+
"utm_source",
|
|
67
|
+
"utm_medium",
|
|
68
|
+
"utm_campaign",
|
|
69
|
+
"utm_term",
|
|
70
|
+
"utm_content"
|
|
71
|
+
];
|
|
72
|
+
const MAX_LENGTH = 200;
|
|
73
|
+
function utmParams(search) {
|
|
74
|
+
var _a;
|
|
75
|
+
const params = new URLSearchParams(search);
|
|
76
|
+
const utm = {};
|
|
77
|
+
for (const key of UTM_KEYS) {
|
|
78
|
+
const value = (_a = params.get(key)) == null ? void 0 : _a.trim().slice(0, MAX_LENGTH);
|
|
79
|
+
if (!value) continue;
|
|
80
|
+
utm[key] = value;
|
|
81
|
+
}
|
|
82
|
+
return utm;
|
|
83
|
+
}
|
|
65
84
|
function parseProps(raw) {
|
|
66
85
|
if (!raw) return void 0;
|
|
67
86
|
try {
|
|
@@ -114,6 +133,11 @@ var __async = (__this, __arguments, generator) => {
|
|
|
114
133
|
if (!global) return payload;
|
|
115
134
|
return __spreadValues(__spreadValues({}, global), payload);
|
|
116
135
|
}
|
|
136
|
+
function withUtm(payload) {
|
|
137
|
+
const utm = utmParams(location.search || "");
|
|
138
|
+
if (Object.keys(utm).length === 0) return payload;
|
|
139
|
+
return __spreadValues(__spreadValues({}, utm), payload);
|
|
140
|
+
}
|
|
117
141
|
const shouldTrack = () => {
|
|
118
142
|
if (trackLocalhost) return true;
|
|
119
143
|
return location.hostname !== "localhost" && location.hostname !== "127.0.0.1";
|
|
@@ -130,7 +154,7 @@ var __async = (__this, __arguments, generator) => {
|
|
|
130
154
|
data: __spreadValues({
|
|
131
155
|
pathname,
|
|
132
156
|
referrer,
|
|
133
|
-
payload: withProps(data == null ? void 0 : data.payload),
|
|
157
|
+
payload: withProps(withUtm(data == null ? void 0 : data.payload)),
|
|
134
158
|
identity: currentIdentity()
|
|
135
159
|
}, browserData)
|
|
136
160
|
});
|
|
Binary file
|
|
Binary file
|
package/dist/utm.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utm.d.ts","sourceRoot":"","sources":["../src/utm.ts"],"names":[],"mappings":"AAUA;;;GAGG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAShE"}
|