@hanzo/event 0.3.22 → 0.3.23
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/LICENSE.md +21 -0
- package/dist/index.cjs +80 -173
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -93
- package/dist/index.d.ts +4 -93
- package/dist/index.mjs +67 -169
- package/dist/index.mjs.map +1 -1
- package/dist/react.cjs +1 -1
- package/dist/react.cjs.map +1 -1
- package/dist/react.mjs +1 -1
- package/dist/react.mjs.map +1 -1
- package/hz.js +1 -1
- package/package.json +11 -11
- package/src/funnels.ts +14 -154
- package/src/goals.test.ts +33 -0
- package/src/version.ts +1 -1
- package/src/funnels.test.ts +0 -92
package/LICENSE.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 hanzo
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/index.cjs
CHANGED
|
@@ -50,16 +50,16 @@ function deriveChannel(a) {
|
|
|
50
50
|
}
|
|
51
51
|
function hostOf(raw) {
|
|
52
52
|
if (!raw) return "";
|
|
53
|
-
let
|
|
54
|
-
const scheme =
|
|
55
|
-
if (scheme >= 0)
|
|
56
|
-
const cut =
|
|
57
|
-
if (cut >= 0)
|
|
58
|
-
const at =
|
|
59
|
-
if (at >= 0)
|
|
60
|
-
const colon =
|
|
61
|
-
if (colon >= 0)
|
|
62
|
-
return
|
|
53
|
+
let s = raw.trim();
|
|
54
|
+
const scheme = s.indexOf("://");
|
|
55
|
+
if (scheme >= 0) s = s.slice(scheme + 3);
|
|
56
|
+
const cut = s.search(/[/?#]/);
|
|
57
|
+
if (cut >= 0) s = s.slice(0, cut);
|
|
58
|
+
const at = s.indexOf("@");
|
|
59
|
+
if (at >= 0) s = s.slice(at + 1);
|
|
60
|
+
const colon = s.indexOf(":");
|
|
61
|
+
if (colon >= 0) s = s.slice(0, colon);
|
|
62
|
+
return s.toLowerCase().trim();
|
|
63
63
|
}
|
|
64
64
|
function hasAttribution(a) {
|
|
65
65
|
return Boolean(
|
|
@@ -139,8 +139,8 @@ function luhn(digits) {
|
|
|
139
139
|
}
|
|
140
140
|
return sum % 10 === 0;
|
|
141
141
|
}
|
|
142
|
-
function redactPAN(
|
|
143
|
-
return
|
|
142
|
+
function redactPAN(s) {
|
|
143
|
+
return s.replace(RE_PAN, (m) => {
|
|
144
144
|
const digits = m.replace(/[ -]/g, "");
|
|
145
145
|
if (digits.length < 13 || digits.length > 19) return m;
|
|
146
146
|
return luhn(digits) ? REDACTED : m;
|
|
@@ -185,30 +185,30 @@ var RE_CREDENTIAL_PARAM = new RegExp(
|
|
|
185
185
|
"([?&#;](?:" + CREDENTIAL_PARAMS.join("|") + ")=)[^&#;\\s]{1,4096}",
|
|
186
186
|
"gi"
|
|
187
187
|
);
|
|
188
|
-
function redactCredentialParams(
|
|
189
|
-
return
|
|
188
|
+
function redactCredentialParams(s) {
|
|
189
|
+
return s.replace(RE_CREDENTIAL_PARAM, (_m, prefix) => prefix + REDACTED);
|
|
190
190
|
}
|
|
191
|
-
function redactSecrets(
|
|
192
|
-
|
|
193
|
-
for (const re of SECRET_PATTERNS)
|
|
194
|
-
return redactPAN(
|
|
191
|
+
function redactSecrets(s) {
|
|
192
|
+
s = redactCredentialParams(s);
|
|
193
|
+
for (const re of SECRET_PATTERNS) s = s.replace(re, REDACTED);
|
|
194
|
+
return redactPAN(s);
|
|
195
195
|
}
|
|
196
|
-
function scrubPII(
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
return
|
|
196
|
+
function scrubPII(s) {
|
|
197
|
+
s = s.replace(RE_EMAIL, EMAIL_MARK);
|
|
198
|
+
s = s.replace(RE_IPV6, IP_MARK);
|
|
199
|
+
s = s.replace(RE_IPV4, IP_MARK);
|
|
200
|
+
return s;
|
|
201
201
|
}
|
|
202
202
|
var MAX_SCRUB_LEN = 8192;
|
|
203
|
-
function truncate(
|
|
204
|
-
return
|
|
203
|
+
function truncate(s, max = MAX_SCRUB_LEN) {
|
|
204
|
+
return s.length > max ? s.slice(0, max) + "\u2026 [truncated]" : s;
|
|
205
205
|
}
|
|
206
|
-
function scrubText(
|
|
207
|
-
if (!
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
if (!capturePII)
|
|
211
|
-
return
|
|
206
|
+
function scrubText(s, capturePII = false) {
|
|
207
|
+
if (!s) return s ?? "";
|
|
208
|
+
s = truncate(s);
|
|
209
|
+
s = redactSecrets(s);
|
|
210
|
+
if (!capturePII) s = scrubPII(s);
|
|
211
|
+
return s;
|
|
212
212
|
}
|
|
213
213
|
|
|
214
214
|
// src/anon.js
|
|
@@ -302,12 +302,12 @@ function hzAnonWrite(name, value) {
|
|
|
302
302
|
}
|
|
303
303
|
function hzAnonId() {
|
|
304
304
|
if (typeof window === "undefined") return "";
|
|
305
|
-
var
|
|
306
|
-
var id = hzAnonCookie(HZ_ANON_KEY) || hzAnonItem(
|
|
305
|
+
var s = hzAnonStore();
|
|
306
|
+
var id = hzAnonCookie(HZ_ANON_KEY) || hzAnonItem(s, HZ_ANON_KEY) || hzAnonItem(s, HZ_ANON_LEGACY_KEY) || hzAnonMemo || hzUuidv7();
|
|
307
307
|
hzAnonMemo = id;
|
|
308
308
|
hzAnonWrite(HZ_ANON_KEY, id);
|
|
309
309
|
try {
|
|
310
|
-
if (
|
|
310
|
+
if (s && s.getItem(HZ_ANON_KEY) !== id) s.setItem(HZ_ANON_KEY, id);
|
|
311
311
|
} catch (e) {
|
|
312
312
|
}
|
|
313
313
|
return id;
|
|
@@ -319,7 +319,7 @@ function uuidv7Time(id) {
|
|
|
319
319
|
}
|
|
320
320
|
|
|
321
321
|
// src/version.ts
|
|
322
|
-
var VERSION = "0.3.
|
|
322
|
+
var VERSION = "0.3.23";
|
|
323
323
|
|
|
324
324
|
// src/sentry.ts
|
|
325
325
|
var MAX_FRAMES = 50;
|
|
@@ -330,10 +330,10 @@ var MAX_TAGS = 50;
|
|
|
330
330
|
function eventId() {
|
|
331
331
|
return hzUuidv7().replace(/-/g, "");
|
|
332
332
|
}
|
|
333
|
-
function byteLen(
|
|
334
|
-
if (typeof TextEncoder !== "undefined") return new TextEncoder().encode(
|
|
335
|
-
if (typeof Buffer !== "undefined") return Buffer.byteLength(
|
|
336
|
-
return
|
|
333
|
+
function byteLen(s) {
|
|
334
|
+
if (typeof TextEncoder !== "undefined") return new TextEncoder().encode(s).length;
|
|
335
|
+
if (typeof Buffer !== "undefined") return Buffer.byteLength(s, "utf8");
|
|
336
|
+
return s.length;
|
|
337
337
|
}
|
|
338
338
|
function parseDsn(dsn) {
|
|
339
339
|
if (!dsn) return null;
|
|
@@ -434,7 +434,7 @@ function str(v) {
|
|
|
434
434
|
}
|
|
435
435
|
}
|
|
436
436
|
function coerceTag(v) {
|
|
437
|
-
const
|
|
437
|
+
const s = typeof v === "string" ? v : (() => {
|
|
438
438
|
try {
|
|
439
439
|
return JSON.stringify(v) ?? String(v);
|
|
440
440
|
} catch {
|
|
@@ -445,7 +445,7 @@ function coerceTag(v) {
|
|
|
445
445
|
}
|
|
446
446
|
}
|
|
447
447
|
})();
|
|
448
|
-
return
|
|
448
|
+
return s.length > MAX_TAG_LEN ? s.slice(0, MAX_TAG_LEN) : s;
|
|
449
449
|
}
|
|
450
450
|
function buildSentryEvent(input) {
|
|
451
451
|
const { error, options = {}, identity, capturePII = false } = input;
|
|
@@ -512,12 +512,12 @@ ${payload}
|
|
|
512
512
|
`;
|
|
513
513
|
}
|
|
514
514
|
var MAX_VALUE = 4096;
|
|
515
|
-
function digest(
|
|
515
|
+
function digest(s) {
|
|
516
516
|
let out = "";
|
|
517
517
|
for (const seed of [2166136261, 16777619, 2654435769, 2246822507]) {
|
|
518
518
|
let h = seed >>> 0;
|
|
519
|
-
for (let i = 0; i <
|
|
520
|
-
h ^=
|
|
519
|
+
for (let i = 0; i < s.length; i++) {
|
|
520
|
+
h ^= s.charCodeAt(i);
|
|
521
521
|
h = h + (h << 1) + (h << 4) + (h << 7) + (h << 8) + (h << 24) >>> 0;
|
|
522
522
|
}
|
|
523
523
|
out += h.toString(16).padStart(8, "0");
|
|
@@ -546,12 +546,12 @@ function frameOf(f) {
|
|
|
546
546
|
module: null
|
|
547
547
|
};
|
|
548
548
|
}
|
|
549
|
-
function truncate2(
|
|
550
|
-
if (
|
|
549
|
+
function truncate2(s, max) {
|
|
550
|
+
if (s.length <= max) return s;
|
|
551
551
|
let end = max;
|
|
552
|
-
const c =
|
|
552
|
+
const c = s.charCodeAt(end - 1);
|
|
553
553
|
if (c >= 55296 && c <= 56319) end--;
|
|
554
|
-
return
|
|
554
|
+
return s.slice(0, end);
|
|
555
555
|
}
|
|
556
556
|
function exceptionEntry(err, opts) {
|
|
557
557
|
const n = normalizeError(err);
|
|
@@ -595,8 +595,8 @@ function exceptionProperties(err, opts) {
|
|
|
595
595
|
$exception_synthetic: entry.mechanism?.synthetic ?? false,
|
|
596
596
|
$exception_types: [entry.type],
|
|
597
597
|
$exception_values: [entry.value],
|
|
598
|
-
$exception_sources: frames.map((f) => f.source).filter((
|
|
599
|
-
$exception_functions: frames.map((f) => f.resolved_name ?? f.mangled_name).filter((
|
|
598
|
+
$exception_sources: frames.map((f) => f.source).filter((s) => !!s),
|
|
599
|
+
$exception_functions: frames.map((f) => f.resolved_name ?? f.mangled_name).filter((s) => !!s)
|
|
600
600
|
};
|
|
601
601
|
}
|
|
602
602
|
|
|
@@ -619,11 +619,11 @@ function anonId() {
|
|
|
619
619
|
return hzAnonId() || void 0;
|
|
620
620
|
}
|
|
621
621
|
function sessionId(now = Date.now()) {
|
|
622
|
-
const
|
|
623
|
-
if (!
|
|
622
|
+
const s = ls();
|
|
623
|
+
if (!s) return void 0;
|
|
624
624
|
let state = null;
|
|
625
625
|
try {
|
|
626
|
-
state = JSON.parse(
|
|
626
|
+
state = JSON.parse(s.getItem(KEY.session) || "null");
|
|
627
627
|
} catch {
|
|
628
628
|
state = null;
|
|
629
629
|
}
|
|
@@ -632,45 +632,45 @@ function sessionId(now = Date.now()) {
|
|
|
632
632
|
} else {
|
|
633
633
|
state.last = now;
|
|
634
634
|
}
|
|
635
|
-
|
|
635
|
+
s.setItem(KEY.session, JSON.stringify(state));
|
|
636
636
|
return state.id;
|
|
637
637
|
}
|
|
638
638
|
function getFirstTouch() {
|
|
639
|
-
const
|
|
640
|
-
if (!
|
|
639
|
+
const s = ls();
|
|
640
|
+
if (!s) return void 0;
|
|
641
641
|
try {
|
|
642
|
-
const v =
|
|
642
|
+
const v = s.getItem(KEY.firstTouch);
|
|
643
643
|
return v ? JSON.parse(v) : void 0;
|
|
644
644
|
} catch {
|
|
645
645
|
return void 0;
|
|
646
646
|
}
|
|
647
647
|
}
|
|
648
648
|
function setFirstTouchOnce(a) {
|
|
649
|
-
const
|
|
649
|
+
const s = ls();
|
|
650
650
|
const existing = getFirstTouch();
|
|
651
651
|
if (existing) return existing;
|
|
652
|
-
if (
|
|
652
|
+
if (s) s.setItem(KEY.firstTouch, JSON.stringify(a));
|
|
653
653
|
return a;
|
|
654
654
|
}
|
|
655
655
|
function getCohort() {
|
|
656
|
-
const
|
|
657
|
-
if (!
|
|
656
|
+
const s = ls();
|
|
657
|
+
if (!s) return void 0;
|
|
658
658
|
try {
|
|
659
|
-
const v =
|
|
659
|
+
const v = s.getItem(KEY.cohort);
|
|
660
660
|
return v ? JSON.parse(v) : void 0;
|
|
661
661
|
} catch {
|
|
662
662
|
return void 0;
|
|
663
663
|
}
|
|
664
664
|
}
|
|
665
665
|
function mergeCohort(patch) {
|
|
666
|
-
const
|
|
666
|
+
const s = ls();
|
|
667
667
|
const cur = getCohort() || {};
|
|
668
668
|
const next = {
|
|
669
669
|
signupWeek: cur.signupWeek || patch.signupWeek,
|
|
670
670
|
channel: patch.channel || cur.channel,
|
|
671
671
|
refCode: cur.refCode || patch.refCode
|
|
672
672
|
};
|
|
673
|
-
if (
|
|
673
|
+
if (s) s.setItem(KEY.cohort, JSON.stringify(next));
|
|
674
674
|
return next;
|
|
675
675
|
}
|
|
676
676
|
|
|
@@ -1030,108 +1030,6 @@ function createAnalytics(config) {
|
|
|
1030
1030
|
return new Analytics(config);
|
|
1031
1031
|
}
|
|
1032
1032
|
|
|
1033
|
-
// src/funnels.ts
|
|
1034
|
-
var PRODUCTS = ["site", "app", "chat", "console", "admin", "cloud"];
|
|
1035
|
-
var s = (event, label, where) => ({
|
|
1036
|
-
event,
|
|
1037
|
-
label,
|
|
1038
|
-
...where ? { where } : {}
|
|
1039
|
-
});
|
|
1040
|
-
var FUNNELS = {
|
|
1041
|
-
/** hanzo.ai: land → sign up. IAM hosts the form, so `signup_submitted` is the
|
|
1042
|
-
* redirect INTO IAM and `signup_completed` is the return at /auth/callback. */
|
|
1043
|
-
signup: {
|
|
1044
|
-
label: "Signup",
|
|
1045
|
-
products: ["site"],
|
|
1046
|
-
join: "person",
|
|
1047
|
-
steps: [
|
|
1048
|
-
s(events.PAGEVIEW, "Landed"),
|
|
1049
|
-
s(events.EVENTS.SIGNUP_VIEWED, "Opened signup"),
|
|
1050
|
-
s(events.EVENTS.SIGNUP_SUBMITTED, "Redirected to Hanzo ID"),
|
|
1051
|
-
s(events.EVENTS.SIGNUP_COMPLETED, "Account created"),
|
|
1052
|
-
s(events.EVENTS.FIRST_ACTION, "First action")
|
|
1053
|
-
]
|
|
1054
|
-
},
|
|
1055
|
-
/** The developer activation path: an account is worth nothing until a key has
|
|
1056
|
-
* made a call. `first_action{action:'api_call'}` is emitted SERVER-SIDE by
|
|
1057
|
-
* Cloud on an org's first successful /v1 request — a browser cannot see it. */
|
|
1058
|
-
apiActivation: {
|
|
1059
|
-
label: "API activation",
|
|
1060
|
-
products: ["site", "cloud"],
|
|
1061
|
-
join: "person",
|
|
1062
|
-
steps: [
|
|
1063
|
-
s(events.EVENTS.SIGNUP_COMPLETED, "Account created"),
|
|
1064
|
-
s(events.EVENTS.API_KEY_CREATED, "Key minted"),
|
|
1065
|
-
s(events.EVENTS.FIRST_ACTION, "First successful API call", {
|
|
1066
|
-
property: "action",
|
|
1067
|
-
equals: "api_call"
|
|
1068
|
-
})
|
|
1069
|
-
]
|
|
1070
|
-
},
|
|
1071
|
-
/** Upgrade intent → revenue. `order_completed{kind:'plan'}` is the Sale goal. */
|
|
1072
|
-
upgrade: {
|
|
1073
|
-
label: "Upgrade",
|
|
1074
|
-
products: ["site", "app", "console"],
|
|
1075
|
-
join: "person",
|
|
1076
|
-
steps: [
|
|
1077
|
-
s(events.EVENTS.PRICING_VIEWED, "Viewed pricing"),
|
|
1078
|
-
s(events.EVENTS.PLAN_CLICKED, "Chose a plan"),
|
|
1079
|
-
s(events.EVENTS.CHECKOUT_STARTED, "Started checkout"),
|
|
1080
|
-
s(events.EVENTS.ORDER_COMPLETED, "Paid")
|
|
1081
|
-
]
|
|
1082
|
-
},
|
|
1083
|
-
/** hanzo.app: describe → build → deploy → live URL. The whole product thesis
|
|
1084
|
-
* in five steps; `deploy_succeeded` is the moment a live URL exists. */
|
|
1085
|
-
appShip: {
|
|
1086
|
-
label: "Describe \u2192 ship",
|
|
1087
|
-
products: ["app"],
|
|
1088
|
-
join: "person",
|
|
1089
|
-
steps: [
|
|
1090
|
-
s(events.PAGEVIEW, "Landed"),
|
|
1091
|
-
s(events.EVENTS.BUILD_STARTED, "Described an app"),
|
|
1092
|
-
s(events.EVENTS.GENERATION_COMPLETED, "Got a working build"),
|
|
1093
|
-
s(events.EVENTS.DEPLOY_STARTED, "Hit publish"),
|
|
1094
|
-
s(events.EVENTS.DEPLOY_SUCCEEDED, "Live URL")
|
|
1095
|
-
]
|
|
1096
|
-
},
|
|
1097
|
-
/** hanzo.chat: visit → first message → answer. `generation_completed` is what
|
|
1098
|
-
* separates "typed something" from "got value". */
|
|
1099
|
-
chatEngage: {
|
|
1100
|
-
label: "Chat engagement",
|
|
1101
|
-
products: ["chat"],
|
|
1102
|
-
join: "person",
|
|
1103
|
-
steps: [
|
|
1104
|
-
s(events.PAGEVIEW, "Landed"),
|
|
1105
|
-
s(events.EVENTS.CHAT_STARTED, "Started a conversation"),
|
|
1106
|
-
s(events.EVENTS.CHAT_MESSAGE_SENT, "Sent a message"),
|
|
1107
|
-
s(events.EVENTS.GENERATION_COMPLETED, "Got an answer")
|
|
1108
|
-
]
|
|
1109
|
-
},
|
|
1110
|
-
/** The cross-surface handoff: the hanzo.ai composer forwards its prompt to
|
|
1111
|
-
* hanzo.chat. Two origins, two anonymousIds — so this is an AGGREGATE funnel.
|
|
1112
|
-
* The join is the `referrerProduct` property hanzo.chat reads off `?hz_ref=`,
|
|
1113
|
-
* which makes the drop-off measurable without any cross-domain identity. */
|
|
1114
|
-
siteToChat: {
|
|
1115
|
-
label: "Site \u2192 Chat handoff",
|
|
1116
|
-
products: ["site", "chat"],
|
|
1117
|
-
join: "aggregate",
|
|
1118
|
-
steps: [
|
|
1119
|
-
s(events.EVENTS.CHAT_STARTED, "Submitted the hanzo.ai composer", {
|
|
1120
|
-
property: "source",
|
|
1121
|
-
equals: "composer"
|
|
1122
|
-
}),
|
|
1123
|
-
s(events.EVENTS.CHAT_STARTED, "Landed in hanzo.chat", {
|
|
1124
|
-
property: "referrerProduct",
|
|
1125
|
-
equals: "site"
|
|
1126
|
-
}),
|
|
1127
|
-
s(events.EVENTS.GENERATION_COMPLETED, "Got an answer")
|
|
1128
|
-
]
|
|
1129
|
-
}
|
|
1130
|
-
};
|
|
1131
|
-
function eventsOf(id) {
|
|
1132
|
-
return FUNNELS[id].steps.map((step) => step.event);
|
|
1133
|
-
}
|
|
1134
|
-
|
|
1135
1033
|
// src/goals.ts
|
|
1136
1034
|
var GOALS = {
|
|
1137
1035
|
// Signup: the conversion is signup_completed, along the site signup funnel.
|
|
@@ -1139,14 +1037,14 @@ var GOALS = {
|
|
|
1139
1037
|
label: "Signup",
|
|
1140
1038
|
event: events.EVENTS.SIGNUP_COMPLETED,
|
|
1141
1039
|
funnelId: "signup",
|
|
1142
|
-
funnel: eventsOf("signup")
|
|
1040
|
+
funnel: events.eventsOf("signup")
|
|
1143
1041
|
},
|
|
1144
1042
|
// Sale: a completed order qualified as a plan purchase (kind=plan).
|
|
1145
1043
|
sale: {
|
|
1146
1044
|
label: "Sale",
|
|
1147
1045
|
event: events.EVENTS.ORDER_COMPLETED,
|
|
1148
1046
|
funnelId: "upgrade",
|
|
1149
|
-
funnel: eventsOf("upgrade"),
|
|
1047
|
+
funnel: events.eventsOf("upgrade"),
|
|
1150
1048
|
filter: { property: "kind", equals: "plan" }
|
|
1151
1049
|
},
|
|
1152
1050
|
// Upgrade intent: a plan click; pricing_viewed is the top of its funnel.
|
|
@@ -1154,7 +1052,7 @@ var GOALS = {
|
|
|
1154
1052
|
label: "Upgrade Intent",
|
|
1155
1053
|
event: events.EVENTS.PLAN_CLICKED,
|
|
1156
1054
|
funnelId: "upgrade",
|
|
1157
|
-
funnel: eventsOf("upgrade")
|
|
1055
|
+
funnel: events.eventsOf("upgrade")
|
|
1158
1056
|
},
|
|
1159
1057
|
// Activation: the ONE north-star conversion — an account that did the first
|
|
1160
1058
|
// valuable thing (a successful API call, a live app, a chat answer).
|
|
@@ -1162,7 +1060,7 @@ var GOALS = {
|
|
|
1162
1060
|
label: "Activation",
|
|
1163
1061
|
event: events.EVENTS.FIRST_ACTION,
|
|
1164
1062
|
funnelId: "apiActivation",
|
|
1165
|
-
funnel: eventsOf("apiActivation")
|
|
1063
|
+
funnel: events.eventsOf("apiActivation")
|
|
1166
1064
|
}
|
|
1167
1065
|
};
|
|
1168
1066
|
var COHORTS = {
|
|
@@ -1200,15 +1098,25 @@ Object.defineProperty(exports, "EXCEPTION", {
|
|
|
1200
1098
|
enumerable: true,
|
|
1201
1099
|
get: function () { return events.EXCEPTION; }
|
|
1202
1100
|
});
|
|
1101
|
+
Object.defineProperty(exports, "FUNNELS", {
|
|
1102
|
+
enumerable: true,
|
|
1103
|
+
get: function () { return events.FUNNELS; }
|
|
1104
|
+
});
|
|
1203
1105
|
Object.defineProperty(exports, "PAGEVIEW", {
|
|
1204
1106
|
enumerable: true,
|
|
1205
1107
|
get: function () { return events.PAGEVIEW; }
|
|
1206
1108
|
});
|
|
1109
|
+
Object.defineProperty(exports, "PRODUCTS", {
|
|
1110
|
+
enumerable: true,
|
|
1111
|
+
get: function () { return events.PRODUCTS; }
|
|
1112
|
+
});
|
|
1113
|
+
Object.defineProperty(exports, "eventsOf", {
|
|
1114
|
+
enumerable: true,
|
|
1115
|
+
get: function () { return events.eventsOf; }
|
|
1116
|
+
});
|
|
1207
1117
|
exports.Analytics = Analytics;
|
|
1208
1118
|
exports.COHORTS = COHORTS;
|
|
1209
|
-
exports.FUNNELS = FUNNELS;
|
|
1210
1119
|
exports.GOALS = GOALS;
|
|
1211
|
-
exports.PRODUCTS = PRODUCTS;
|
|
1212
1120
|
exports.PRODUCT_PROJECT = PRODUCT_PROJECT;
|
|
1213
1121
|
exports.VERSION = VERSION;
|
|
1214
1122
|
exports.buildEnvelope = buildEnvelope;
|
|
@@ -1217,7 +1125,6 @@ exports.createAnalytics = createAnalytics;
|
|
|
1217
1125
|
exports.deriveChannel = deriveChannel;
|
|
1218
1126
|
exports.digest = digest;
|
|
1219
1127
|
exports.dsnForProduct = dsnForProduct;
|
|
1220
|
-
exports.eventsOf = eventsOf;
|
|
1221
1128
|
exports.exceptionEntry = exceptionEntry;
|
|
1222
1129
|
exports.exceptionProperties = exceptionProperties;
|
|
1223
1130
|
exports.fingerprint = fingerprint;
|