kanmi-perf-revenue 1.0.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 +347 -173
- package/dist/empirical/ab-testing.d.ts +83 -0
- package/dist/empirical/ab-testing.d.ts.map +1 -0
- package/dist/empirical/ab-testing.js +281 -0
- package/dist/empirical/ab-testing.js.map +1 -0
- package/dist/empirical/alerting.d.ts +85 -0
- package/dist/empirical/alerting.d.ts.map +1 -0
- package/dist/empirical/alerting.js +358 -0
- package/dist/empirical/alerting.js.map +1 -0
- package/dist/empirical/attribution.d.ts +80 -0
- package/dist/empirical/attribution.d.ts.map +1 -0
- package/dist/empirical/attribution.js +305 -0
- package/dist/empirical/attribution.js.map +1 -0
- package/dist/empirical/cohort.d.ts +75 -0
- package/dist/empirical/cohort.d.ts.map +1 -0
- package/dist/empirical/cohort.js +305 -0
- package/dist/empirical/cohort.js.map +1 -0
- package/dist/empirical/conversion-curve.d.ts +7 -10
- package/dist/empirical/conversion-curve.d.ts.map +1 -1
- package/dist/empirical/conversion-curve.js +37 -4
- package/dist/empirical/conversion-curve.js.map +1 -1
- package/dist/empirical/correlation.d.ts +91 -0
- package/dist/empirical/correlation.d.ts.map +1 -0
- package/dist/empirical/correlation.js +461 -0
- package/dist/empirical/correlation.js.map +1 -0
- package/dist/empirical/data-import.d.ts +22 -0
- package/dist/empirical/data-import.d.ts.map +1 -1
- package/dist/empirical/data-import.js +44 -0
- package/dist/empirical/data-import.js.map +1 -1
- package/dist/empirical/datadog-product-analytics.d.ts +192 -0
- package/dist/empirical/datadog-product-analytics.d.ts.map +1 -0
- package/dist/empirical/datadog-product-analytics.js +632 -0
- package/dist/empirical/datadog-product-analytics.js.map +1 -0
- package/dist/empirical/datadog-session-query.d.ts +32 -0
- package/dist/empirical/datadog-session-query.d.ts.map +1 -1
- package/dist/empirical/datadog-session-query.js +238 -17
- package/dist/empirical/datadog-session-query.js.map +1 -1
- package/dist/empirical/engagement-analysis.d.ts +112 -0
- package/dist/empirical/engagement-analysis.d.ts.map +1 -0
- package/dist/empirical/engagement-analysis.js +354 -0
- package/dist/empirical/engagement-analysis.js.map +1 -0
- package/dist/empirical/export.d.ts +75 -0
- package/dist/empirical/export.d.ts.map +1 -0
- package/dist/empirical/export.js +392 -0
- package/dist/empirical/export.js.map +1 -0
- package/dist/empirical/forecasting.d.ts +80 -0
- package/dist/empirical/forecasting.d.ts.map +1 -0
- package/dist/empirical/forecasting.js +287 -0
- package/dist/empirical/forecasting.js.map +1 -0
- package/dist/empirical/funnel.d.ts +66 -0
- package/dist/empirical/funnel.d.ts.map +1 -0
- package/dist/empirical/funnel.js +293 -0
- package/dist/empirical/funnel.js.map +1 -0
- package/dist/empirical/history.d.ts +198 -0
- package/dist/empirical/history.d.ts.map +1 -0
- package/dist/empirical/history.js +396 -0
- package/dist/empirical/history.js.map +1 -0
- package/dist/empirical/index.d.ts +41 -16
- package/dist/empirical/index.d.ts.map +1 -1
- package/dist/empirical/index.js +96 -13
- package/dist/empirical/index.js.map +1 -1
- package/dist/empirical/interactions.d.ts +89 -0
- package/dist/empirical/interactions.d.ts.map +1 -0
- package/dist/empirical/interactions.js +346 -0
- package/dist/empirical/interactions.js.map +1 -0
- package/dist/empirical/opportunity-calculator.d.ts +6 -18
- package/dist/empirical/opportunity-calculator.d.ts.map +1 -1
- package/dist/empirical/opportunity-calculator.js +19 -1
- package/dist/empirical/opportunity-calculator.js.map +1 -1
- package/dist/empirical/report.d.ts +3 -11
- package/dist/empirical/report.d.ts.map +1 -1
- package/dist/empirical/report.js +11 -7
- package/dist/empirical/report.js.map +1 -1
- package/dist/empirical/roi-calculator.d.ts +104 -0
- package/dist/empirical/roi-calculator.d.ts.map +1 -0
- package/dist/empirical/roi-calculator.js +403 -0
- package/dist/empirical/roi-calculator.js.map +1 -0
- package/dist/empirical/seasonality.d.ts +80 -0
- package/dist/empirical/seasonality.d.ts.map +1 -0
- package/dist/empirical/seasonality.js +340 -0
- package/dist/empirical/seasonality.js.map +1 -0
- package/dist/empirical/segmentation.d.ts +135 -0
- package/dist/empirical/segmentation.d.ts.map +1 -0
- package/dist/empirical/segmentation.js +379 -0
- package/dist/empirical/segmentation.js.map +1 -0
- package/dist/empirical/statistics.d.ts +118 -0
- package/dist/empirical/statistics.d.ts.map +1 -0
- package/dist/empirical/statistics.js +344 -0
- package/dist/empirical/statistics.js.map +1 -0
- package/dist/empirical/sweet-spot.d.ts +81 -0
- package/dist/empirical/sweet-spot.d.ts.map +1 -0
- package/dist/empirical/sweet-spot.js +198 -0
- package/dist/empirical/sweet-spot.js.map +1 -0
- package/package.json +2 -2
|
@@ -0,0 +1,379 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Segmentation Analysis
|
|
3
|
+
*
|
|
4
|
+
* Analyze conversion rates and performance impact by segment:
|
|
5
|
+
* - Device (mobile, desktop, tablet)
|
|
6
|
+
* - Page type (PDP, PLP, checkout, homepage)
|
|
7
|
+
* - Geography (country, region)
|
|
8
|
+
* - Traffic source (organic, paid, direct, social, etc.)
|
|
9
|
+
* - Custom events (purchase, add_to_cart, signup, lead)
|
|
10
|
+
*
|
|
11
|
+
* @author Kanmi Obasa <i@kanmiobasa.com>
|
|
12
|
+
*/
|
|
13
|
+
// =============================================================================
|
|
14
|
+
// SEGMENTATION ANALYSIS
|
|
15
|
+
// =============================================================================
|
|
16
|
+
/**
|
|
17
|
+
* Analyze sessions by a specific segment.
|
|
18
|
+
*/
|
|
19
|
+
export function analyzeBySegment(sessions, segmentType, eventName = 'purchase') {
|
|
20
|
+
const segments = new Map();
|
|
21
|
+
// Group sessions by segment
|
|
22
|
+
for (const session of sessions) {
|
|
23
|
+
const segmentValue = getSegmentValue(session, segmentType);
|
|
24
|
+
if (!segmentValue)
|
|
25
|
+
continue;
|
|
26
|
+
if (!segments.has(segmentValue)) {
|
|
27
|
+
segments.set(segmentValue, []);
|
|
28
|
+
}
|
|
29
|
+
segments.get(segmentValue).push(session);
|
|
30
|
+
}
|
|
31
|
+
const totalSessions = sessions.length;
|
|
32
|
+
const stats = [];
|
|
33
|
+
for (const [name, segmentSessions] of segments) {
|
|
34
|
+
const conversions = segmentSessions.filter(s => hasConversionEvent(s, eventName)).length;
|
|
35
|
+
const revenue = segmentSessions.reduce((sum, s) => sum + getEventValue(s, eventName), 0);
|
|
36
|
+
const bounces = segmentSessions.filter(s => s.bounced).length;
|
|
37
|
+
const totalPageViews = segmentSessions.reduce((sum, s) => sum + s.page_views, 0);
|
|
38
|
+
stats.push({
|
|
39
|
+
name,
|
|
40
|
+
sessions: segmentSessions.length,
|
|
41
|
+
session_pct: segmentSessions.length / totalSessions,
|
|
42
|
+
conversions,
|
|
43
|
+
cvr: segmentSessions.length > 0 ? conversions / segmentSessions.length : 0,
|
|
44
|
+
revenue,
|
|
45
|
+
aov: conversions > 0 ? revenue / conversions : 0,
|
|
46
|
+
performance: {
|
|
47
|
+
lcp_p50: percentile(segmentSessions.map(s => s.lcp_ms).filter(v => v !== null), 50),
|
|
48
|
+
fcp_p50: percentile(segmentSessions.map(s => s.fcp_ms).filter(v => v !== null), 50),
|
|
49
|
+
inp_p50: percentile(segmentSessions.map(s => s.inp_ms).filter(v => v !== null), 50),
|
|
50
|
+
cls_p50: percentile(segmentSessions.map(s => s.cls).filter(v => v !== null), 50),
|
|
51
|
+
ttfb_p50: percentile(segmentSessions.map(s => s.ttfb_ms).filter(v => v !== null), 50),
|
|
52
|
+
},
|
|
53
|
+
bounce_rate: segmentSessions.length > 0 ? bounces / segmentSessions.length : 0,
|
|
54
|
+
avg_page_views: segmentSessions.length > 0 ? totalPageViews / segmentSessions.length : 0,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
// Sort by sessions descending
|
|
58
|
+
stats.sort((a, b) => b.sessions - a.sessions);
|
|
59
|
+
return stats;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Compare segments to find significant differences.
|
|
63
|
+
*/
|
|
64
|
+
export function compareSegments(stats, baselineName) {
|
|
65
|
+
if (stats.length < 2)
|
|
66
|
+
return [];
|
|
67
|
+
// Use the largest segment as baseline if not specified
|
|
68
|
+
const baseline = baselineName
|
|
69
|
+
? stats.find(s => s.name === baselineName)
|
|
70
|
+
: stats[0];
|
|
71
|
+
if (!baseline)
|
|
72
|
+
return [];
|
|
73
|
+
const comparisons = [];
|
|
74
|
+
for (const segment of stats) {
|
|
75
|
+
if (segment.name === baseline.name)
|
|
76
|
+
continue;
|
|
77
|
+
const cvrDiff = segment.cvr - baseline.cvr;
|
|
78
|
+
const cvrRelativeDiff = baseline.cvr > 0 ? cvrDiff / baseline.cvr : 0;
|
|
79
|
+
// Simple significance check: both segments need sufficient sample size
|
|
80
|
+
// and the difference should be meaningful (>5% relative)
|
|
81
|
+
const isSignificant = segment.sessions >= 100 &&
|
|
82
|
+
baseline.sessions >= 100 &&
|
|
83
|
+
Math.abs(cvrRelativeDiff) >= 0.05;
|
|
84
|
+
const direction = cvrDiff > 0 ? 'higher' : 'lower';
|
|
85
|
+
const pctDiff = Math.abs(cvrRelativeDiff * 100).toFixed(1);
|
|
86
|
+
comparisons.push({
|
|
87
|
+
segment: segment.name,
|
|
88
|
+
baseline: baseline.name,
|
|
89
|
+
cvr_diff: cvrDiff,
|
|
90
|
+
cvr_relative_diff: cvrRelativeDiff,
|
|
91
|
+
is_significant: isSignificant,
|
|
92
|
+
insight: isSignificant
|
|
93
|
+
? `${segment.name} converts ${pctDiff}% ${direction} than ${baseline.name}`
|
|
94
|
+
: `No significant difference between ${segment.name} and ${baseline.name}`,
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
// Sort by absolute CVR difference
|
|
98
|
+
comparisons.sort((a, b) => Math.abs(b.cvr_relative_diff) - Math.abs(a.cvr_relative_diff));
|
|
99
|
+
return comparisons;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Analyze conversion events across all sessions.
|
|
103
|
+
*/
|
|
104
|
+
export function analyzeEvents(sessions) {
|
|
105
|
+
const eventMap = new Map();
|
|
106
|
+
for (const session of sessions) {
|
|
107
|
+
for (const event of session.conversions) {
|
|
108
|
+
if (!eventMap.has(event.name)) {
|
|
109
|
+
eventMap.set(event.name, { sessions: new Set(), totalValue: 0, count: 0 });
|
|
110
|
+
}
|
|
111
|
+
const stats = eventMap.get(event.name);
|
|
112
|
+
stats.sessions.add(session.session_id);
|
|
113
|
+
stats.totalValue += event.value;
|
|
114
|
+
stats.count++;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
const totalSessions = sessions.length;
|
|
118
|
+
const eventStats = [];
|
|
119
|
+
for (const [name, data] of eventMap) {
|
|
120
|
+
eventStats.push({
|
|
121
|
+
name,
|
|
122
|
+
sessions: data.sessions.size,
|
|
123
|
+
rate: totalSessions > 0 ? data.sessions.size / totalSessions : 0,
|
|
124
|
+
total_value: data.totalValue,
|
|
125
|
+
avg_value: data.count > 0 ? data.totalValue / data.count : 0,
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
// Sort by event rate descending
|
|
129
|
+
eventStats.sort((a, b) => b.rate - a.rate);
|
|
130
|
+
return eventStats;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Generate a complete segmentation report.
|
|
134
|
+
*/
|
|
135
|
+
export function generateSegmentationReport(sessions, eventName = 'purchase') {
|
|
136
|
+
// Analyze each segment type
|
|
137
|
+
const deviceStats = analyzeBySegment(sessions, 'device', eventName);
|
|
138
|
+
const deviceComparisons = compareSegments(deviceStats, 'desktop');
|
|
139
|
+
const pageTypeStats = analyzeBySegment(sessions, 'page_type', eventName);
|
|
140
|
+
const pageTypeComparisons = compareSegments(pageTypeStats);
|
|
141
|
+
const countryStats = analyzeBySegment(sessions, 'country', eventName);
|
|
142
|
+
const countryComparisons = compareSegments(countryStats);
|
|
143
|
+
const trafficStats = analyzeBySegment(sessions, 'traffic_source', eventName);
|
|
144
|
+
const trafficComparisons = compareSegments(trafficStats);
|
|
145
|
+
const eventStats = analyzeEvents(sessions);
|
|
146
|
+
// Find highest and lowest CVR segments
|
|
147
|
+
const allStats = [
|
|
148
|
+
...deviceStats.map(s => ({ type: 'device', ...s })),
|
|
149
|
+
...pageTypeStats.map(s => ({ type: 'page_type', ...s })),
|
|
150
|
+
...countryStats.map(s => ({ type: 'country', ...s })),
|
|
151
|
+
...trafficStats.map(s => ({ type: 'traffic_source', ...s })),
|
|
152
|
+
].filter(s => s.sessions >= 100); // Only consider segments with sufficient data
|
|
153
|
+
const highestCvr = allStats.reduce((max, s) => s.cvr > max.cvr ? s : max, allStats[0]);
|
|
154
|
+
const lowestCvr = allStats.reduce((min, s) => s.cvr < min.cvr ? s : min, allStats[0]);
|
|
155
|
+
// Find biggest opportunity (largest segment with below-average CVR)
|
|
156
|
+
const overallCvr = sessions.filter(s => hasConversionEvent(s, eventName)).length / sessions.length;
|
|
157
|
+
const opportunities = allStats
|
|
158
|
+
.filter(s => s.cvr < overallCvr && s.sessions >= 500)
|
|
159
|
+
.sort((a, b) => (b.sessions * (overallCvr - b.cvr)) - (a.sessions * (overallCvr - a.cvr)));
|
|
160
|
+
const biggestOpportunity = opportunities[0]
|
|
161
|
+
? `${opportunities[0].type}: ${opportunities[0].name} (${opportunities[0].sessions.toLocaleString()} sessions, ${(opportunities[0].cvr * 100).toFixed(2)}% CVR vs ${(overallCvr * 100).toFixed(2)}% overall)`
|
|
162
|
+
: 'No significant opportunities identified';
|
|
163
|
+
return {
|
|
164
|
+
by_device: {
|
|
165
|
+
segments: deviceStats,
|
|
166
|
+
comparisons: deviceComparisons,
|
|
167
|
+
insight: generateDeviceInsight(deviceStats, deviceComparisons),
|
|
168
|
+
},
|
|
169
|
+
by_page_type: {
|
|
170
|
+
segments: pageTypeStats,
|
|
171
|
+
comparisons: pageTypeComparisons,
|
|
172
|
+
insight: generatePageTypeInsight(pageTypeStats),
|
|
173
|
+
},
|
|
174
|
+
by_country: {
|
|
175
|
+
segments: countryStats,
|
|
176
|
+
comparisons: countryComparisons,
|
|
177
|
+
insight: generateCountryInsight(countryStats, countryComparisons),
|
|
178
|
+
},
|
|
179
|
+
by_traffic_source: {
|
|
180
|
+
segments: trafficStats,
|
|
181
|
+
comparisons: trafficComparisons,
|
|
182
|
+
insight: generateTrafficInsight(trafficStats, trafficComparisons),
|
|
183
|
+
},
|
|
184
|
+
by_event_type: {
|
|
185
|
+
events: eventStats,
|
|
186
|
+
insight: generateEventInsight(eventStats),
|
|
187
|
+
},
|
|
188
|
+
summary: {
|
|
189
|
+
total_sessions: sessions.length,
|
|
190
|
+
highest_cvr_segment: highestCvr
|
|
191
|
+
? { type: highestCvr.type, name: highestCvr.name, cvr: highestCvr.cvr }
|
|
192
|
+
: { type: 'unknown', name: 'unknown', cvr: 0 },
|
|
193
|
+
lowest_cvr_segment: lowestCvr
|
|
194
|
+
? { type: lowestCvr.type, name: lowestCvr.name, cvr: lowestCvr.cvr }
|
|
195
|
+
: { type: 'unknown', name: 'unknown', cvr: 0 },
|
|
196
|
+
biggest_opportunity: biggestOpportunity,
|
|
197
|
+
},
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Generate markdown report for segmentation analysis.
|
|
202
|
+
*/
|
|
203
|
+
export function generateSegmentationMarkdown(report) {
|
|
204
|
+
const lines = [];
|
|
205
|
+
lines.push('# Segmentation Analysis Report');
|
|
206
|
+
lines.push('');
|
|
207
|
+
lines.push(`**Total Sessions:** ${report.summary.total_sessions.toLocaleString()}`);
|
|
208
|
+
lines.push('');
|
|
209
|
+
// Summary
|
|
210
|
+
lines.push('## Key Findings');
|
|
211
|
+
lines.push('');
|
|
212
|
+
lines.push(`- **Highest CVR:** ${report.summary.highest_cvr_segment.type} = ${report.summary.highest_cvr_segment.name} (${(report.summary.highest_cvr_segment.cvr * 100).toFixed(2)}%)`);
|
|
213
|
+
lines.push(`- **Lowest CVR:** ${report.summary.lowest_cvr_segment.type} = ${report.summary.lowest_cvr_segment.name} (${(report.summary.lowest_cvr_segment.cvr * 100).toFixed(2)}%)`);
|
|
214
|
+
lines.push(`- **Biggest Opportunity:** ${report.summary.biggest_opportunity}`);
|
|
215
|
+
lines.push('');
|
|
216
|
+
// Device Analysis
|
|
217
|
+
lines.push('## By Device');
|
|
218
|
+
lines.push('');
|
|
219
|
+
lines.push(report.by_device.insight);
|
|
220
|
+
lines.push('');
|
|
221
|
+
lines.push('| Device | Sessions | CVR | Revenue | LCP p50 | Bounce Rate |');
|
|
222
|
+
lines.push('|--------|----------|-----|---------|---------|-------------|');
|
|
223
|
+
for (const seg of report.by_device.segments) {
|
|
224
|
+
const lcpStr = seg.performance.lcp_p50 ? `${(seg.performance.lcp_p50 / 1000).toFixed(1)}s` : '-';
|
|
225
|
+
lines.push(`| ${seg.name} | ${seg.sessions.toLocaleString()} | ${(seg.cvr * 100).toFixed(2)}% | $${formatCurrency(seg.revenue)} | ${lcpStr} | ${(seg.bounce_rate * 100).toFixed(1)}% |`);
|
|
226
|
+
}
|
|
227
|
+
lines.push('');
|
|
228
|
+
// Page Type Analysis
|
|
229
|
+
lines.push('## By Page Type');
|
|
230
|
+
lines.push('');
|
|
231
|
+
lines.push(report.by_page_type.insight);
|
|
232
|
+
lines.push('');
|
|
233
|
+
lines.push('| Page Type | Sessions | CVR | Revenue | Avg Page Views |');
|
|
234
|
+
lines.push('|-----------|----------|-----|---------|----------------|');
|
|
235
|
+
for (const seg of report.by_page_type.segments) {
|
|
236
|
+
lines.push(`| ${seg.name} | ${seg.sessions.toLocaleString()} | ${(seg.cvr * 100).toFixed(2)}% | $${formatCurrency(seg.revenue)} | ${seg.avg_page_views.toFixed(1)} |`);
|
|
237
|
+
}
|
|
238
|
+
lines.push('');
|
|
239
|
+
// Traffic Source Analysis
|
|
240
|
+
lines.push('## By Traffic Source');
|
|
241
|
+
lines.push('');
|
|
242
|
+
lines.push(report.by_traffic_source.insight);
|
|
243
|
+
lines.push('');
|
|
244
|
+
lines.push('| Source | Sessions | CVR | Revenue | AOV |');
|
|
245
|
+
lines.push('|--------|----------|-----|---------|-----|');
|
|
246
|
+
for (const seg of report.by_traffic_source.segments) {
|
|
247
|
+
lines.push(`| ${seg.name} | ${seg.sessions.toLocaleString()} | ${(seg.cvr * 100).toFixed(2)}% | $${formatCurrency(seg.revenue)} | $${seg.aov.toFixed(0)} |`);
|
|
248
|
+
}
|
|
249
|
+
lines.push('');
|
|
250
|
+
// Country Analysis (top 5)
|
|
251
|
+
lines.push('## By Country (Top 5)');
|
|
252
|
+
lines.push('');
|
|
253
|
+
lines.push(report.by_country.insight);
|
|
254
|
+
lines.push('');
|
|
255
|
+
lines.push('| Country | Sessions | CVR | Revenue |');
|
|
256
|
+
lines.push('|---------|----------|-----|---------|');
|
|
257
|
+
for (const seg of report.by_country.segments.slice(0, 5)) {
|
|
258
|
+
lines.push(`| ${seg.name} | ${seg.sessions.toLocaleString()} | ${(seg.cvr * 100).toFixed(2)}% | $${formatCurrency(seg.revenue)} |`);
|
|
259
|
+
}
|
|
260
|
+
lines.push('');
|
|
261
|
+
// Event Analysis
|
|
262
|
+
lines.push('## Conversion Events');
|
|
263
|
+
lines.push('');
|
|
264
|
+
lines.push(report.by_event_type.insight);
|
|
265
|
+
lines.push('');
|
|
266
|
+
lines.push('| Event | Sessions | Rate | Total Value | Avg Value |');
|
|
267
|
+
lines.push('|-------|----------|------|-------------|-----------|');
|
|
268
|
+
for (const event of report.by_event_type.events) {
|
|
269
|
+
lines.push(`| ${event.name} | ${event.sessions.toLocaleString()} | ${(event.rate * 100).toFixed(2)}% | $${formatCurrency(event.total_value)} | $${event.avg_value.toFixed(0)} |`);
|
|
270
|
+
}
|
|
271
|
+
lines.push('');
|
|
272
|
+
lines.push('---');
|
|
273
|
+
lines.push('*Generated by Empirical Performance Revenue Engine*');
|
|
274
|
+
return lines.join('\n');
|
|
275
|
+
}
|
|
276
|
+
// =============================================================================
|
|
277
|
+
// HELPERS
|
|
278
|
+
// =============================================================================
|
|
279
|
+
function getSegmentValue(session, segmentType) {
|
|
280
|
+
switch (segmentType) {
|
|
281
|
+
case 'device':
|
|
282
|
+
return session.device;
|
|
283
|
+
case 'page_type':
|
|
284
|
+
return session.page_type;
|
|
285
|
+
case 'country':
|
|
286
|
+
return session.country;
|
|
287
|
+
case 'traffic_source':
|
|
288
|
+
return session.traffic_source;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
function hasConversionEvent(session, eventName) {
|
|
292
|
+
if (eventName === 'purchase') {
|
|
293
|
+
return session.has_purchase;
|
|
294
|
+
}
|
|
295
|
+
return session.conversions.some(e => e.name === eventName);
|
|
296
|
+
}
|
|
297
|
+
function getEventValue(session, eventName) {
|
|
298
|
+
if (eventName === 'purchase') {
|
|
299
|
+
return session.purchase_value;
|
|
300
|
+
}
|
|
301
|
+
const events = session.conversions.filter(e => e.name === eventName);
|
|
302
|
+
return events.reduce((sum, e) => sum + e.value, 0);
|
|
303
|
+
}
|
|
304
|
+
function percentile(values, p) {
|
|
305
|
+
if (values.length === 0)
|
|
306
|
+
return null;
|
|
307
|
+
const sorted = [...values].sort((a, b) => a - b);
|
|
308
|
+
const index = Math.ceil((p / 100) * sorted.length) - 1;
|
|
309
|
+
return sorted[Math.max(0, index)];
|
|
310
|
+
}
|
|
311
|
+
function formatCurrency(value) {
|
|
312
|
+
if (value >= 1_000_000) {
|
|
313
|
+
return `${(value / 1_000_000).toFixed(1)}M`;
|
|
314
|
+
}
|
|
315
|
+
if (value >= 1_000) {
|
|
316
|
+
return `${Math.round(value / 1_000)}K`;
|
|
317
|
+
}
|
|
318
|
+
return Math.round(value).toString();
|
|
319
|
+
}
|
|
320
|
+
function generateDeviceInsight(stats, comparisons) {
|
|
321
|
+
const mobile = stats.find(s => s.name === 'mobile');
|
|
322
|
+
const desktop = stats.find(s => s.name === 'desktop');
|
|
323
|
+
if (!mobile || !desktop)
|
|
324
|
+
return 'Insufficient device data.';
|
|
325
|
+
const mobileVsDesktop = comparisons.find(c => c.segment === 'mobile');
|
|
326
|
+
if (mobileVsDesktop?.is_significant) {
|
|
327
|
+
const direction = mobileVsDesktop.cvr_diff > 0 ? 'outperforms' : 'underperforms';
|
|
328
|
+
const pct = Math.abs(mobileVsDesktop.cvr_relative_diff * 100).toFixed(0);
|
|
329
|
+
return `Mobile ${direction} desktop by ${pct}%. Mobile LCP p50: ${mobile.performance.lcp_p50 ? (mobile.performance.lcp_p50 / 1000).toFixed(1) + 's' : 'N/A'} vs Desktop: ${desktop.performance.lcp_p50 ? (desktop.performance.lcp_p50 / 1000).toFixed(1) + 's' : 'N/A'}.`;
|
|
330
|
+
}
|
|
331
|
+
return 'No significant difference between mobile and desktop conversion rates.';
|
|
332
|
+
}
|
|
333
|
+
function generatePageTypeInsight(stats) {
|
|
334
|
+
const checkout = stats.find(s => s.name === 'checkout');
|
|
335
|
+
const pdp = stats.find(s => s.name === 'pdp');
|
|
336
|
+
if (checkout && checkout.cvr > 0) {
|
|
337
|
+
return `Checkout pages have ${(checkout.cvr * 100).toFixed(1)}% CVR. Focus performance optimization here for maximum impact.`;
|
|
338
|
+
}
|
|
339
|
+
if (pdp) {
|
|
340
|
+
return `Product detail pages (PDP) represent ${(pdp.session_pct * 100).toFixed(0)}% of sessions with ${(pdp.cvr * 100).toFixed(2)}% CVR.`;
|
|
341
|
+
}
|
|
342
|
+
return 'Page type analysis shows varied conversion rates across different page types.';
|
|
343
|
+
}
|
|
344
|
+
function generateCountryInsight(_stats, comparisons) {
|
|
345
|
+
const significant = comparisons.filter(c => c.is_significant);
|
|
346
|
+
if (significant.length === 0) {
|
|
347
|
+
return 'No significant CVR differences between countries.';
|
|
348
|
+
}
|
|
349
|
+
const worstPerformer = significant.find(c => c.cvr_diff < 0);
|
|
350
|
+
if (worstPerformer) {
|
|
351
|
+
const pct = Math.abs(worstPerformer.cvr_relative_diff * 100).toFixed(0);
|
|
352
|
+
return `${worstPerformer.segment} converts ${pct}% lower than ${worstPerformer.baseline}. Consider localized performance optimization.`;
|
|
353
|
+
}
|
|
354
|
+
return `${significant.length} countries show significant CVR differences.`;
|
|
355
|
+
}
|
|
356
|
+
function generateTrafficInsight(stats, _comparisons) {
|
|
357
|
+
const paid = stats.find(s => s.name === 'paid');
|
|
358
|
+
const organic = stats.find(s => s.name === 'organic');
|
|
359
|
+
if (paid && organic) {
|
|
360
|
+
const diff = ((paid.cvr - organic.cvr) / organic.cvr * 100).toFixed(0);
|
|
361
|
+
const direction = paid.cvr > organic.cvr ? 'higher' : 'lower';
|
|
362
|
+
return `Paid traffic converts ${Math.abs(Number(diff))}% ${direction} than organic. Paid AOV: $${paid.aov.toFixed(0)}, Organic AOV: $${organic.aov.toFixed(0)}.`;
|
|
363
|
+
}
|
|
364
|
+
const topSource = stats[0];
|
|
365
|
+
return `${topSource.name} is the largest traffic source (${(topSource.session_pct * 100).toFixed(0)}% of sessions) with ${(topSource.cvr * 100).toFixed(2)}% CVR.`;
|
|
366
|
+
}
|
|
367
|
+
function generateEventInsight(events) {
|
|
368
|
+
const purchase = events.find(e => e.name === 'purchase');
|
|
369
|
+
const addToCart = events.find(e => e.name === 'add_to_cart');
|
|
370
|
+
if (purchase && addToCart) {
|
|
371
|
+
const cartToPurchase = purchase.sessions / addToCart.sessions;
|
|
372
|
+
return `${(addToCart.rate * 100).toFixed(1)}% add to cart rate, ${(cartToPurchase * 100).toFixed(0)}% cart-to-purchase conversion.`;
|
|
373
|
+
}
|
|
374
|
+
if (events.length > 0) {
|
|
375
|
+
return `Tracking ${events.length} conversion events. Top event: ${events[0].name} (${(events[0].rate * 100).toFixed(2)}% rate).`;
|
|
376
|
+
}
|
|
377
|
+
return 'No conversion events tracked.';
|
|
378
|
+
}
|
|
379
|
+
//# sourceMappingURL=segmentation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"segmentation.js","sourceRoot":"","sources":["../../src/empirical/segmentation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Statistical Significance Analysis
|
|
3
|
+
*
|
|
4
|
+
* Provides statistical rigor for conversion rate comparisons:
|
|
5
|
+
* - Confidence intervals for CVR
|
|
6
|
+
* - Two-proportion z-tests for comparing CVR between groups
|
|
7
|
+
* - Sample size recommendations
|
|
8
|
+
* - Effect size calculations
|
|
9
|
+
*
|
|
10
|
+
* @author Kanmi Obasa <i@kanmiobasa.com>
|
|
11
|
+
*/
|
|
12
|
+
export interface ConfidenceInterval {
|
|
13
|
+
/** Point estimate (e.g., CVR) */
|
|
14
|
+
estimate: number;
|
|
15
|
+
/** Lower bound of interval */
|
|
16
|
+
lower: number;
|
|
17
|
+
/** Upper bound of interval */
|
|
18
|
+
upper: number;
|
|
19
|
+
/** Confidence level (e.g., 0.95 for 95%) */
|
|
20
|
+
confidence_level: number;
|
|
21
|
+
/** Margin of error */
|
|
22
|
+
margin_of_error: number;
|
|
23
|
+
}
|
|
24
|
+
export interface ProportionTest {
|
|
25
|
+
/** Group A statistics */
|
|
26
|
+
group_a: {
|
|
27
|
+
name: string;
|
|
28
|
+
conversions: number;
|
|
29
|
+
sessions: number;
|
|
30
|
+
cvr: number;
|
|
31
|
+
ci: ConfidenceInterval;
|
|
32
|
+
};
|
|
33
|
+
/** Group B statistics */
|
|
34
|
+
group_b: {
|
|
35
|
+
name: string;
|
|
36
|
+
conversions: number;
|
|
37
|
+
sessions: number;
|
|
38
|
+
cvr: number;
|
|
39
|
+
ci: ConfidenceInterval;
|
|
40
|
+
};
|
|
41
|
+
/** Absolute difference (A - B) */
|
|
42
|
+
absolute_diff: number;
|
|
43
|
+
/** Relative difference ((A - B) / B) */
|
|
44
|
+
relative_diff: number;
|
|
45
|
+
/** Z-score */
|
|
46
|
+
z_score: number;
|
|
47
|
+
/** P-value (two-tailed) */
|
|
48
|
+
p_value: number;
|
|
49
|
+
/** Is the difference statistically significant? */
|
|
50
|
+
is_significant: boolean;
|
|
51
|
+
/** Significance level used */
|
|
52
|
+
alpha: number;
|
|
53
|
+
/** Statistical power (approximate) */
|
|
54
|
+
power: number;
|
|
55
|
+
/** Insight text */
|
|
56
|
+
insight: string;
|
|
57
|
+
}
|
|
58
|
+
export interface SampleSizeRecommendation {
|
|
59
|
+
/** Baseline CVR */
|
|
60
|
+
baseline_cvr: number;
|
|
61
|
+
/** Minimum detectable effect (relative) */
|
|
62
|
+
mde: number;
|
|
63
|
+
/** Required sample size per group */
|
|
64
|
+
sample_size_per_group: number;
|
|
65
|
+
/** Significance level */
|
|
66
|
+
alpha: number;
|
|
67
|
+
/** Statistical power */
|
|
68
|
+
power: number;
|
|
69
|
+
}
|
|
70
|
+
export interface EffectSize {
|
|
71
|
+
/** Cohen's h for proportion differences */
|
|
72
|
+
cohens_h: number;
|
|
73
|
+
/** Interpretation */
|
|
74
|
+
interpretation: 'negligible' | 'small' | 'medium' | 'large';
|
|
75
|
+
/** Relative lift */
|
|
76
|
+
relative_lift: number;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Calculate confidence interval for a proportion using Wilson score interval.
|
|
80
|
+
* More accurate than normal approximation, especially for small samples.
|
|
81
|
+
*/
|
|
82
|
+
export declare function calculateConfidenceInterval(conversions: number, sessions: number, confidenceLevel?: number): ConfidenceInterval;
|
|
83
|
+
/**
|
|
84
|
+
* Calculate confidence interval for the difference between two proportions.
|
|
85
|
+
*/
|
|
86
|
+
export declare function calculateDifferenceCI(conversionsA: number, sessionsA: number, conversionsB: number, sessionsB: number, confidenceLevel?: number): ConfidenceInterval;
|
|
87
|
+
/**
|
|
88
|
+
* Two-proportion z-test to compare conversion rates.
|
|
89
|
+
*/
|
|
90
|
+
export declare function twoProportionZTest(groupAName: string, conversionsA: number, sessionsA: number, groupBName: string, conversionsB: number, sessionsB: number, alpha?: number): ProportionTest;
|
|
91
|
+
/**
|
|
92
|
+
* Calculate effect size (Cohen's h) for proportion differences.
|
|
93
|
+
*/
|
|
94
|
+
export declare function calculateEffectSize(pA: number, pB: number): EffectSize;
|
|
95
|
+
/**
|
|
96
|
+
* Calculate required sample size for detecting a given effect.
|
|
97
|
+
*/
|
|
98
|
+
export declare function calculateRequiredSampleSize(baselineCvr: number, minDetectableEffect: number, // Relative (e.g., 0.10 for 10% lift)
|
|
99
|
+
alpha?: number, power?: number): SampleSizeRecommendation;
|
|
100
|
+
/**
|
|
101
|
+
* Check if current sample size is sufficient.
|
|
102
|
+
*/
|
|
103
|
+
export declare function isSampleSufficient(sessions: number, baselineCvr: number, minDetectableEffect?: number, alpha?: number, power?: number): {
|
|
104
|
+
sufficient: boolean;
|
|
105
|
+
current: number;
|
|
106
|
+
required: number;
|
|
107
|
+
recommendation: string;
|
|
108
|
+
};
|
|
109
|
+
/**
|
|
110
|
+
* Apply Bonferroni correction for multiple comparisons.
|
|
111
|
+
*/
|
|
112
|
+
export declare function bonferroniCorrection(alpha: number, numComparisons: number): number;
|
|
113
|
+
/**
|
|
114
|
+
* Apply Benjamini-Hochberg FDR correction.
|
|
115
|
+
* Returns adjusted p-values.
|
|
116
|
+
*/
|
|
117
|
+
export declare function benjaminiHochbergCorrection(pValues: number[]): number[];
|
|
118
|
+
//# sourceMappingURL=statistics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"statistics.d.ts","sourceRoot":"","sources":["../../src/empirical/statistics.ts"],"names":[],"mappings":"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"}
|