@coursebuilder/analytics 1.1.0 → 1.1.2-canary.0.0c9beb2ae
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/api/index.d.ts +22 -2
- package/dist/api/index.js +40 -5
- package/dist/api/index.js.map +1 -1
- package/dist/catalog.d.ts +1 -1
- package/dist/catalog.js +43 -1
- package/dist/catalog.js.map +1 -1
- package/dist/components/index.d.ts +46 -1
- package/dist/components/index.js +200 -8
- package/dist/components/index.js.map +1 -1
- package/dist/engine.js +94 -6
- package/dist/engine.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +94 -6
- package/dist/index.js.map +1 -1
- package/dist/providers/database.d.ts +174 -2
- package/dist/providers/database.js +711 -20
- package/dist/providers/database.js.map +1 -1
- package/dist/providers/index.js +713 -22
- package/dist/providers/index.js.map +1 -1
- package/dist/providers/survey.d.ts +1 -1
- package/dist/providers/survey.js +2 -2
- package/dist/providers/survey.js.map +1 -1
- package/dist/types.d.ts +189 -3
- package/package.json +7 -5
- package/src/api/catalog-handler.ts +44 -2
- package/src/api/token-handler.ts +3 -2
- package/src/catalog.ts +49 -1
- package/src/components/omnibus-dashboard.tsx +340 -6
- package/src/engine.ts +69 -8
- package/src/providers/attribution-recovery.test.ts +63 -0
- package/src/providers/attribution-recovery.ts +97 -0
- package/src/providers/database.ts +880 -42
- package/src/providers/survey.ts +3 -1
- package/src/types.ts +215 -2
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
export const SHORTLINK_RECOVERY_LANE =
|
|
2
|
+
'recovered_from_shortlink_attribution_table' as const
|
|
3
|
+
|
|
4
|
+
export type PurchaseAttributionClass =
|
|
5
|
+
| 'purchase_field'
|
|
6
|
+
| typeof SHORTLINK_RECOVERY_LANE
|
|
7
|
+
| 'dark'
|
|
8
|
+
|
|
9
|
+
export interface ShortlinkAttributionEvidence {
|
|
10
|
+
type?: string | null
|
|
11
|
+
metadata?: unknown
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
15
|
+
return Boolean(value) && typeof value === 'object' && !Array.isArray(value)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function nonEmptyString(value: unknown) {
|
|
19
|
+
return typeof value === 'string' && value.trim().length > 0
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function parseMetadata(value: unknown): Record<string, unknown> | null {
|
|
23
|
+
if (typeof value === 'string') {
|
|
24
|
+
try {
|
|
25
|
+
const parsed = JSON.parse(value) as unknown
|
|
26
|
+
return isRecord(parsed) ? parsed : null
|
|
27
|
+
} catch {
|
|
28
|
+
return null
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return isRecord(value) ? value : null
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Detects durable purchase-field attribution on a purchase fields object.
|
|
37
|
+
*
|
|
38
|
+
* @param fields Unknown purchase fields payload.
|
|
39
|
+
* @returns True when the purchase already has attribution, legacy UTM source, or legacy GA client ID evidence.
|
|
40
|
+
* @example
|
|
41
|
+
* hasPurchaseFieldAttribution({ attribution: { source: 'email' } })
|
|
42
|
+
*/
|
|
43
|
+
export function hasPurchaseFieldAttribution(fields: unknown) {
|
|
44
|
+
const record = isRecord(fields) ? fields : {}
|
|
45
|
+
const attribution = record.attribution
|
|
46
|
+
|
|
47
|
+
return Boolean(
|
|
48
|
+
(isRecord(attribution) && Object.keys(attribution).length > 0) ||
|
|
49
|
+
nonEmptyString(record.utmSource) ||
|
|
50
|
+
nonEmptyString(record.gaClientId),
|
|
51
|
+
)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Detects exact shortlink purchase evidence for one purchase.
|
|
56
|
+
*
|
|
57
|
+
* @param params.purchaseId Purchase ID that must match attribution metadata.purchaseId.
|
|
58
|
+
* @param params.attributions ShortlinkAttributionEvidence rows to inspect.
|
|
59
|
+
* @returns True only for purchase rows with valid JSON metadata and an exact purchase ID match.
|
|
60
|
+
*/
|
|
61
|
+
export function hasExactShortlinkPurchaseAttribution(params: {
|
|
62
|
+
purchaseId: string
|
|
63
|
+
attributions: readonly ShortlinkAttributionEvidence[]
|
|
64
|
+
}) {
|
|
65
|
+
return params.attributions.some((attribution) => {
|
|
66
|
+
if (attribution.type !== 'purchase') return false
|
|
67
|
+
const metadata = parseMetadata(attribution.metadata)
|
|
68
|
+
return metadata?.purchaseId === params.purchaseId
|
|
69
|
+
})
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Classifies purchase attribution with purchase fields taking precedence.
|
|
74
|
+
*
|
|
75
|
+
* @param params.purchaseId Purchase ID being classified.
|
|
76
|
+
* @param params.fields Purchase fields payload.
|
|
77
|
+
* @param params.shortlinkAttributions ShortlinkAttributionEvidence rows used as exact fallback evidence.
|
|
78
|
+
* @returns A PurchaseAttributionClass: 'purchase_field', SHORTLINK_RECOVERY_LANE, or 'dark'.
|
|
79
|
+
* @example
|
|
80
|
+
* classifyPurchaseAttribution({ purchaseId: 'p1', fields: {}, shortlinkAttributions: [] })
|
|
81
|
+
*/
|
|
82
|
+
export function classifyPurchaseAttribution(params: {
|
|
83
|
+
purchaseId: string
|
|
84
|
+
fields?: unknown
|
|
85
|
+
shortlinkAttributions?: readonly ShortlinkAttributionEvidence[]
|
|
86
|
+
}): PurchaseAttributionClass {
|
|
87
|
+
if (hasPurchaseFieldAttribution(params.fields)) return 'purchase_field'
|
|
88
|
+
if (
|
|
89
|
+
hasExactShortlinkPurchaseAttribution({
|
|
90
|
+
purchaseId: params.purchaseId,
|
|
91
|
+
attributions: params.shortlinkAttributions ?? [],
|
|
92
|
+
})
|
|
93
|
+
) {
|
|
94
|
+
return SHORTLINK_RECOVERY_LANE
|
|
95
|
+
}
|
|
96
|
+
return 'dark'
|
|
97
|
+
}
|