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,346 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Multi-Metric Interaction Analysis
|
|
3
|
+
*
|
|
4
|
+
* Analyzes how combinations of performance metrics affect conversion rates.
|
|
5
|
+
* Goes beyond single-metric analysis to find interaction effects.
|
|
6
|
+
*
|
|
7
|
+
* Key insights:
|
|
8
|
+
* - Do users with both good LCP AND good INP convert better than expected?
|
|
9
|
+
* - Are there threshold combinations that matter?
|
|
10
|
+
* - Which metric pairs have synergistic effects?
|
|
11
|
+
*
|
|
12
|
+
* @author Kanmi Obasa <i@kanmiobasa.com>
|
|
13
|
+
*/
|
|
14
|
+
// =============================================================================
|
|
15
|
+
// THRESHOLDS (Core Web Vitals standards)
|
|
16
|
+
// =============================================================================
|
|
17
|
+
const METRIC_THRESHOLDS = {
|
|
18
|
+
lcp: { good: 2500, poor: 4000 },
|
|
19
|
+
inp: { good: 200, poor: 500 },
|
|
20
|
+
cls: { good: 0.1, poor: 0.25 },
|
|
21
|
+
fcp: { good: 1800, poor: 3000 },
|
|
22
|
+
ttfb: { good: 800, poor: 1800 },
|
|
23
|
+
};
|
|
24
|
+
// =============================================================================
|
|
25
|
+
// CORE ANALYSIS
|
|
26
|
+
// =============================================================================
|
|
27
|
+
/**
|
|
28
|
+
* Get metric value from session.
|
|
29
|
+
*/
|
|
30
|
+
function getMetricValue(session, metric) {
|
|
31
|
+
switch (metric) {
|
|
32
|
+
case 'lcp':
|
|
33
|
+
return session.lcp_ms;
|
|
34
|
+
case 'inp':
|
|
35
|
+
return session.inp_ms;
|
|
36
|
+
case 'cls':
|
|
37
|
+
return session.cls;
|
|
38
|
+
case 'fcp':
|
|
39
|
+
return session.fcp_ms;
|
|
40
|
+
case 'ttfb':
|
|
41
|
+
return session.ttfb_ms;
|
|
42
|
+
default:
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Classify metric value into bucket.
|
|
48
|
+
*/
|
|
49
|
+
function classifyMetric(value, thresholds) {
|
|
50
|
+
if (value === null)
|
|
51
|
+
return null;
|
|
52
|
+
if (value <= thresholds.good)
|
|
53
|
+
return 'good';
|
|
54
|
+
if (value >= thresholds.poor)
|
|
55
|
+
return 'poor';
|
|
56
|
+
return 'needs_improvement';
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Analyze interaction between two metrics.
|
|
60
|
+
*/
|
|
61
|
+
export function analyzeMetricInteraction(sessions, metricA, metricB) {
|
|
62
|
+
const thresholdsA = METRIC_THRESHOLDS[metricA];
|
|
63
|
+
const thresholdsB = METRIC_THRESHOLDS[metricB];
|
|
64
|
+
// Classify each session
|
|
65
|
+
const classified = [];
|
|
66
|
+
for (const session of sessions) {
|
|
67
|
+
const valueA = getMetricValue(session, metricA);
|
|
68
|
+
const valueB = getMetricValue(session, metricB);
|
|
69
|
+
const bucketA = classifyMetric(valueA, thresholdsA);
|
|
70
|
+
const bucketB = classifyMetric(valueB, thresholdsB);
|
|
71
|
+
if (bucketA && bucketB) {
|
|
72
|
+
classified.push({
|
|
73
|
+
bucketA,
|
|
74
|
+
bucketB,
|
|
75
|
+
converted: session.has_purchase,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
if (classified.length < 100)
|
|
80
|
+
return null; // Need sufficient data
|
|
81
|
+
// Build 3x3 grid
|
|
82
|
+
const buckets = [
|
|
83
|
+
'good',
|
|
84
|
+
'needs_improvement',
|
|
85
|
+
'poor',
|
|
86
|
+
];
|
|
87
|
+
// Calculate marginal CVRs
|
|
88
|
+
const marginalsA = {};
|
|
89
|
+
const marginalsB = {};
|
|
90
|
+
for (const bucket of buckets) {
|
|
91
|
+
marginalsA[bucket] = { sessions: 0, conversions: 0 };
|
|
92
|
+
marginalsB[bucket] = { sessions: 0, conversions: 0 };
|
|
93
|
+
}
|
|
94
|
+
for (const item of classified) {
|
|
95
|
+
marginalsA[item.bucketA].sessions++;
|
|
96
|
+
marginalsB[item.bucketB].sessions++;
|
|
97
|
+
if (item.converted) {
|
|
98
|
+
marginalsA[item.bucketA].conversions++;
|
|
99
|
+
marginalsB[item.bucketB].conversions++;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
const overallCvr = classified.filter((c) => c.converted).length / classified.length;
|
|
103
|
+
// Build grid
|
|
104
|
+
const grid = [];
|
|
105
|
+
let bestCell = null;
|
|
106
|
+
let worstCell = null;
|
|
107
|
+
let totalInteractionEffect = 0;
|
|
108
|
+
let cellCount = 0;
|
|
109
|
+
for (let i = 0; i < buckets.length; i++) {
|
|
110
|
+
grid[i] = [];
|
|
111
|
+
for (let j = 0; j < buckets.length; j++) {
|
|
112
|
+
const bucketA = buckets[i];
|
|
113
|
+
const bucketB = buckets[j];
|
|
114
|
+
const cellData = classified.filter((c) => c.bucketA === bucketA && c.bucketB === bucketB);
|
|
115
|
+
const cellSessions = cellData.length;
|
|
116
|
+
const cellConversions = cellData.filter((c) => c.converted).length;
|
|
117
|
+
const cvr = cellSessions > 0 ? cellConversions / cellSessions : 0;
|
|
118
|
+
// Expected CVR based on marginals (independence assumption)
|
|
119
|
+
const cvrA = marginalsA[bucketA].sessions > 0
|
|
120
|
+
? marginalsA[bucketA].conversions / marginalsA[bucketA].sessions
|
|
121
|
+
: overallCvr;
|
|
122
|
+
const cvrB = marginalsB[bucketB].sessions > 0
|
|
123
|
+
? marginalsB[bucketB].conversions / marginalsB[bucketB].sessions
|
|
124
|
+
: overallCvr;
|
|
125
|
+
// Expected under independence: P(convert | A) * P(convert | B) / P(convert)
|
|
126
|
+
// Simplified: average of the two marginal effects
|
|
127
|
+
const expectedCvr = (cvrA + cvrB) / 2;
|
|
128
|
+
const interactionEffect = cvr - expectedCvr;
|
|
129
|
+
const cell = {
|
|
130
|
+
metricABucket: bucketA,
|
|
131
|
+
metricBBucket: bucketB,
|
|
132
|
+
sessions: cellSessions,
|
|
133
|
+
conversions: cellConversions,
|
|
134
|
+
cvr,
|
|
135
|
+
expectedCvr,
|
|
136
|
+
interactionEffect,
|
|
137
|
+
synergistic: interactionEffect > 0,
|
|
138
|
+
};
|
|
139
|
+
grid[i][j] = cell;
|
|
140
|
+
if (cellSessions >= 10) {
|
|
141
|
+
// Only consider cells with sufficient data
|
|
142
|
+
totalInteractionEffect += Math.abs(interactionEffect);
|
|
143
|
+
cellCount++;
|
|
144
|
+
if (!bestCell || cvr > bestCell.cvr) {
|
|
145
|
+
bestCell = cell;
|
|
146
|
+
}
|
|
147
|
+
if (!worstCell || cvr < worstCell.cvr) {
|
|
148
|
+
worstCell = cell;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
const interactionStrength = cellCount > 0 ? totalInteractionEffect / cellCount : 0;
|
|
154
|
+
// Generate insights
|
|
155
|
+
const insights = [];
|
|
156
|
+
// Check for synergy in good-good cell
|
|
157
|
+
const goodGood = grid[0][0];
|
|
158
|
+
if (goodGood.sessions >= 10 && goodGood.interactionEffect > 0.005) {
|
|
159
|
+
insights.push(`Synergy: Good ${metricA.toUpperCase()} + Good ${metricB.toUpperCase()} converts ${(goodGood.interactionEffect * 100).toFixed(2)}% better than expected`);
|
|
160
|
+
}
|
|
161
|
+
// Check for compounding poor performance
|
|
162
|
+
const poorPoor = grid[2][2];
|
|
163
|
+
if (poorPoor.sessions >= 10 && poorPoor.interactionEffect < -0.005) {
|
|
164
|
+
insights.push(`Compound penalty: Poor ${metricA.toUpperCase()} + Poor ${metricB.toUpperCase()} converts ${Math.abs(poorPoor.interactionEffect * 100).toFixed(2)}% worse than expected`);
|
|
165
|
+
}
|
|
166
|
+
// Compare good-good vs poor-poor
|
|
167
|
+
if (goodGood.sessions >= 10 && poorPoor.sessions >= 10 && goodGood.cvr > 0) {
|
|
168
|
+
const lift = ((goodGood.cvr - poorPoor.cvr) / poorPoor.cvr) * 100;
|
|
169
|
+
if (lift > 20) {
|
|
170
|
+
insights.push(`Combined impact: ${lift.toFixed(0)}% higher CVR when both metrics are good vs both poor`);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return {
|
|
174
|
+
metricA,
|
|
175
|
+
metricB,
|
|
176
|
+
grid,
|
|
177
|
+
interactionStrength,
|
|
178
|
+
insights,
|
|
179
|
+
bestCombination: bestCell
|
|
180
|
+
? {
|
|
181
|
+
metricA: bestCell.metricABucket,
|
|
182
|
+
metricB: bestCell.metricBBucket,
|
|
183
|
+
cvr: bestCell.cvr,
|
|
184
|
+
lift: bestCell.cvr > overallCvr ? (bestCell.cvr - overallCvr) / overallCvr : 0,
|
|
185
|
+
}
|
|
186
|
+
: { metricA: 'good', metricB: 'good', cvr: overallCvr, lift: 0 },
|
|
187
|
+
worstCombination: worstCell
|
|
188
|
+
? {
|
|
189
|
+
metricA: worstCell.metricABucket,
|
|
190
|
+
metricB: worstCell.metricBBucket,
|
|
191
|
+
cvr: worstCell.cvr,
|
|
192
|
+
}
|
|
193
|
+
: { metricA: 'poor', metricB: 'poor', cvr: overallCvr },
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Analyze all pairwise metric interactions.
|
|
198
|
+
*/
|
|
199
|
+
export function analyzeAllInteractions(sessions) {
|
|
200
|
+
const metrics = ['lcp', 'inp', 'cls', 'fcp', 'ttfb'];
|
|
201
|
+
const interactions = [];
|
|
202
|
+
// Analyze all pairs
|
|
203
|
+
for (let i = 0; i < metrics.length; i++) {
|
|
204
|
+
for (let j = i + 1; j < metrics.length; j++) {
|
|
205
|
+
const interaction = analyzeMetricInteraction(sessions, metrics[i], metrics[j]);
|
|
206
|
+
if (interaction) {
|
|
207
|
+
interactions.push(interaction);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
// Rank by interaction strength
|
|
212
|
+
const rankedInteractions = interactions
|
|
213
|
+
.map((i) => ({
|
|
214
|
+
metricA: i.metricA,
|
|
215
|
+
metricB: i.metricB,
|
|
216
|
+
strength: i.interactionStrength,
|
|
217
|
+
}))
|
|
218
|
+
.sort((a, b) => b.strength - a.strength);
|
|
219
|
+
// Generate findings
|
|
220
|
+
const findings = [];
|
|
221
|
+
if (rankedInteractions.length > 0) {
|
|
222
|
+
const top = rankedInteractions[0];
|
|
223
|
+
findings.push(`Strongest interaction: ${top.metricA.toUpperCase()} × ${top.metricB.toUpperCase()} (strength: ${(top.strength * 100).toFixed(2)}%)`);
|
|
224
|
+
}
|
|
225
|
+
// Collect all insights
|
|
226
|
+
for (const interaction of interactions.slice(0, 3)) {
|
|
227
|
+
findings.push(...interaction.insights.slice(0, 2));
|
|
228
|
+
}
|
|
229
|
+
// Generate recommendations
|
|
230
|
+
const recommendations = [];
|
|
231
|
+
// Find the metric pair with highest synergy in good-good
|
|
232
|
+
let bestSynergy = null;
|
|
233
|
+
for (const interaction of interactions) {
|
|
234
|
+
const goodGood = interaction.grid[0][0];
|
|
235
|
+
if (goodGood.sessions >= 10 && goodGood.interactionEffect > 0) {
|
|
236
|
+
if (!bestSynergy || goodGood.interactionEffect > bestSynergy.effect) {
|
|
237
|
+
bestSynergy = {
|
|
238
|
+
pair: `${interaction.metricA.toUpperCase()} + ${interaction.metricB.toUpperCase()}`,
|
|
239
|
+
effect: goodGood.interactionEffect,
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
if (bestSynergy) {
|
|
245
|
+
recommendations.push(`Prioritize improving both ${bestSynergy.pair} together for synergistic gains`);
|
|
246
|
+
}
|
|
247
|
+
// Find worst compound penalty
|
|
248
|
+
let worstPenalty = null;
|
|
249
|
+
for (const interaction of interactions) {
|
|
250
|
+
const poorPoor = interaction.grid[2][2];
|
|
251
|
+
if (poorPoor.sessions >= 10 && poorPoor.interactionEffect < 0) {
|
|
252
|
+
if (!worstPenalty || poorPoor.interactionEffect < worstPenalty.effect) {
|
|
253
|
+
worstPenalty = {
|
|
254
|
+
pair: `${interaction.metricA.toUpperCase()} + ${interaction.metricB.toUpperCase()}`,
|
|
255
|
+
effect: poorPoor.interactionEffect,
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
if (worstPenalty) {
|
|
261
|
+
recommendations.push(`Address ${worstPenalty.pair} together - compound penalty of ${Math.abs(worstPenalty.effect * 100).toFixed(2)}%`);
|
|
262
|
+
}
|
|
263
|
+
return {
|
|
264
|
+
interactions,
|
|
265
|
+
rankedInteractions,
|
|
266
|
+
findings,
|
|
267
|
+
recommendations,
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
// =============================================================================
|
|
271
|
+
// REPORT GENERATION
|
|
272
|
+
// =============================================================================
|
|
273
|
+
/**
|
|
274
|
+
* Generate markdown report for interaction analysis.
|
|
275
|
+
*/
|
|
276
|
+
export function generateInteractionMarkdown(report) {
|
|
277
|
+
const lines = [];
|
|
278
|
+
lines.push('## Multi-Metric Interaction Analysis');
|
|
279
|
+
lines.push('');
|
|
280
|
+
lines.push('How combinations of performance metrics affect conversion rates beyond individual effects.');
|
|
281
|
+
lines.push('');
|
|
282
|
+
// Key Findings
|
|
283
|
+
if (report.findings.length > 0) {
|
|
284
|
+
lines.push('### Key Findings');
|
|
285
|
+
lines.push('');
|
|
286
|
+
for (const finding of report.findings) {
|
|
287
|
+
lines.push(`- ${finding}`);
|
|
288
|
+
}
|
|
289
|
+
lines.push('');
|
|
290
|
+
}
|
|
291
|
+
// Recommendations
|
|
292
|
+
if (report.recommendations.length > 0) {
|
|
293
|
+
lines.push('### Recommendations');
|
|
294
|
+
lines.push('');
|
|
295
|
+
for (const rec of report.recommendations) {
|
|
296
|
+
lines.push(`- ${rec}`);
|
|
297
|
+
}
|
|
298
|
+
lines.push('');
|
|
299
|
+
}
|
|
300
|
+
// Interaction Strength Ranking
|
|
301
|
+
if (report.rankedInteractions.length > 0) {
|
|
302
|
+
lines.push('### Interaction Strength Ranking');
|
|
303
|
+
lines.push('');
|
|
304
|
+
lines.push('| Metric Pair | Interaction Strength |');
|
|
305
|
+
lines.push('|-------------|---------------------|');
|
|
306
|
+
for (const ranked of report.rankedInteractions) {
|
|
307
|
+
lines.push(`| ${ranked.metricA.toUpperCase()} × ${ranked.metricB.toUpperCase()} | ${(ranked.strength * 100).toFixed(2)}% |`);
|
|
308
|
+
}
|
|
309
|
+
lines.push('');
|
|
310
|
+
}
|
|
311
|
+
// Detailed grids for top interactions
|
|
312
|
+
const topInteractions = report.interactions.slice(0, 3);
|
|
313
|
+
for (const interaction of topInteractions) {
|
|
314
|
+
lines.push(`### ${interaction.metricA.toUpperCase()} × ${interaction.metricB.toUpperCase()}`);
|
|
315
|
+
lines.push('');
|
|
316
|
+
lines.push(`| | Good ${interaction.metricB.toUpperCase()} | Needs Imp. | Poor ${interaction.metricB.toUpperCase()} |`);
|
|
317
|
+
lines.push('|---|---|---|---|');
|
|
318
|
+
const rowLabels = [`Good ${interaction.metricA.toUpperCase()}`, 'Needs Imp.', `Poor ${interaction.metricA.toUpperCase()}`];
|
|
319
|
+
for (let i = 0; i < 3; i++) {
|
|
320
|
+
const cells = interaction.grid[i];
|
|
321
|
+
const row = [
|
|
322
|
+
rowLabels[i],
|
|
323
|
+
formatCell(cells[0]),
|
|
324
|
+
formatCell(cells[1]),
|
|
325
|
+
formatCell(cells[2]),
|
|
326
|
+
];
|
|
327
|
+
lines.push(`| ${row.join(' | ')} |`);
|
|
328
|
+
}
|
|
329
|
+
lines.push('');
|
|
330
|
+
if (interaction.insights.length > 0) {
|
|
331
|
+
lines.push('**Insights:**');
|
|
332
|
+
for (const insight of interaction.insights) {
|
|
333
|
+
lines.push(`- ${insight}`);
|
|
334
|
+
}
|
|
335
|
+
lines.push('');
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
return lines.join('\n');
|
|
339
|
+
}
|
|
340
|
+
function formatCell(cell) {
|
|
341
|
+
if (cell.sessions < 10)
|
|
342
|
+
return `${(cell.cvr * 100).toFixed(1)}% (n=${cell.sessions})`;
|
|
343
|
+
const indicator = cell.synergistic ? '↑' : '↓';
|
|
344
|
+
return `${(cell.cvr * 100).toFixed(2)}% ${indicator}`;
|
|
345
|
+
}
|
|
346
|
+
//# sourceMappingURL=interactions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interactions.js","sourceRoot":"","sources":["../../src/empirical/interactions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AA2EH,gFAAgF;AAChF,yCAAyC;AACzC,gFAAgF;AAEhF,MAAM,iBAAiB,GAAyC;IAC9D,GAAG,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE;IAC/B,GAAG,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE;IAC7B,GAAG,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE;IAC9B,GAAG,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE;IAC/B,IAAI,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE;CAChC,CAAC;AAEF,gFAAgF;AAChF,gBAAgB;AAChB,gFAAgF;AAEhF;;GAEG;AACH,SAAS,cAAc,CAAC,OAAoB,EAAE,MAAkB;IAC9D,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,KAAK;YACR,OAAO,OAAO,CAAC,MAAM,CAAC;QACxB,KAAK,KAAK;YACR,OAAO,OAAO,CAAC,MAAM,CAAC;QACxB,KAAK,KAAK;YACR,OAAO,OAAO,CAAC,GAAG,CAAC;QACrB,KAAK,KAAK;YACR,OAAO,OAAO,CAAC,MAAM,CAAC;QACxB,KAAK,MAAM;YACT,OAAO,OAAO,CAAC,OAAO,CAAC;QACzB;YACE,OAAO,IAAI,CAAC;IAChB,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,cAAc,CACrB,KAAoB,EACpB,UAA4B;IAE5B,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAChC,IAAI,KAAK,IAAI,UAAU,CAAC,IAAI;QAAE,OAAO,MAAM,CAAC;IAC5C,IAAI,KAAK,IAAI,UAAU,CAAC,IAAI;QAAE,OAAO,MAAM,CAAC;IAC5C,OAAO,mBAAmB,CAAC;AAC7B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,wBAAwB,CACtC,QAAuB,EACvB,OAAmB,EACnB,OAAmB;IAEnB,MAAM,WAAW,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;IAC/C,MAAM,WAAW,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;IAE/C,wBAAwB;IACxB,MAAM,UAAU,GAIX,EAAE,CAAC;IAER,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,MAAM,MAAM,GAAG,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAChD,MAAM,MAAM,GAAG,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAChD,MAAM,OAAO,GAAG,cAAc,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;QACpD,MAAM,OAAO,GAAG,cAAc,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;QAEpD,IAAI,OAAO,IAAI,OAAO,EAAE,CAAC;YACvB,UAAU,CAAC,IAAI,CAAC;gBACd,OAAO;gBACP,OAAO;gBACP,SAAS,EAAE,OAAO,CAAC,YAAY;aAChC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,IAAI,UAAU,CAAC,MAAM,GAAG,GAAG;QAAE,OAAO,IAAI,CAAC,CAAC,uBAAuB;IAEjE,iBAAiB;IACjB,MAAM,OAAO,GAAiD;QAC5D,MAAM;QACN,mBAAmB;QACnB,MAAM;KACP,CAAC;IAEF,0BAA0B;IAC1B,MAAM,UAAU,GAA8D,EAAE,CAAC;IACjF,MAAM,UAAU,GAA8D,EAAE,CAAC;IAEjF,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,UAAU,CAAC,MAAM,CAAC,GAAG,EAAE,QAAQ,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC;QACrD,UAAU,CAAC,MAAM,CAAC,GAAG,EAAE,QAAQ,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC;IACvD,CAAC;IAED,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;QAC9B,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,CAAC;QACpC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,CAAC;QACpC,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACnB,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC;YACvC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC;QACzC,CAAC;IACH,CAAC;IAED,MAAM,UAAU,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC;IAEpF,aAAa;IACb,MAAM,IAAI,GAAwB,EAAE,CAAC;IACrC,IAAI,QAAQ,GAA2B,IAAI,CAAC;IAC5C,IAAI,SAAS,GAA2B,IAAI,CAAC;IAC7C,IAAI,sBAAsB,GAAG,CAAC,CAAC;IAC/B,IAAI,SAAS,GAAG,CAAC,CAAC;IAElB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACxC,IAAI,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;QACb,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACxC,MAAM,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;YAC3B,MAAM,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;YAE3B,MAAM,QAAQ,GAAG,UAAU,CAAC,MAAM,CAChC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,OAAO,IAAI,CAAC,CAAC,OAAO,KAAK,OAAO,CACtD,CAAC;YACF,MAAM,YAAY,GAAG,QAAQ,CAAC,MAAM,CAAC;YACrC,MAAM,eAAe,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC;YACnE,MAAM,GAAG,GAAG,YAAY,GAAG,CAAC,CAAC,CAAC,CAAC,eAAe,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;YAElE,4DAA4D;YAC5D,MAAM,IAAI,GACR,UAAU,CAAC,OAAO,CAAC,CAAC,QAAQ,GAAG,CAAC;gBAC9B,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,WAAW,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC,QAAQ;gBAChE,CAAC,CAAC,UAAU,CAAC;YACjB,MAAM,IAAI,GACR,UAAU,CAAC,OAAO,CAAC,CAAC,QAAQ,GAAG,CAAC;gBAC9B,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,WAAW,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC,QAAQ;gBAChE,CAAC,CAAC,UAAU,CAAC;YAEjB,4EAA4E;YAC5E,kDAAkD;YAClD,MAAM,WAAW,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;YAEtC,MAAM,iBAAiB,GAAG,GAAG,GAAG,WAAW,CAAC;YAE5C,MAAM,IAAI,GAAoB;gBAC5B,aAAa,EAAE,OAAO;gBACtB,aAAa,EAAE,OAAO;gBACtB,QAAQ,EAAE,YAAY;gBACtB,WAAW,EAAE,eAAe;gBAC5B,GAAG;gBACH,WAAW;gBACX,iBAAiB;gBACjB,WAAW,EAAE,iBAAiB,GAAG,CAAC;aACnC,CAAC;YAEF,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;YAElB,IAAI,YAAY,IAAI,EAAE,EAAE,CAAC;gBACvB,2CAA2C;gBAC3C,sBAAsB,IAAI,IAAI,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;gBACtD,SAAS,EAAE,CAAC;gBAEZ,IAAI,CAAC,QAAQ,IAAI,GAAG,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC;oBACpC,QAAQ,GAAG,IAAI,CAAC;gBAClB,CAAC;gBACD,IAAI,CAAC,SAAS,IAAI,GAAG,GAAG,SAAS,CAAC,GAAG,EAAE,CAAC;oBACtC,SAAS,GAAG,IAAI,CAAC;gBACnB,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,mBAAmB,GAAG,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,sBAAsB,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;IAEnF,oBAAoB;IACpB,MAAM,QAAQ,GAAa,EAAE,CAAC;IAE9B,sCAAsC;IACtC,MAAM,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5B,IAAI,QAAQ,CAAC,QAAQ,IAAI,EAAE,IAAI,QAAQ,CAAC,iBAAiB,GAAG,KAAK,EAAE,CAAC;QAClE,QAAQ,CAAC,IAAI,CACX,iBAAiB,OAAO,CAAC,WAAW,EAAE,WAAW,OAAO,CAAC,WAAW,EAAE,aAAa,CAAC,QAAQ,CAAC,iBAAiB,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,wBAAwB,CACzJ,CAAC;IACJ,CAAC;IAED,yCAAyC;IACzC,MAAM,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5B,IAAI,QAAQ,CAAC,QAAQ,IAAI,EAAE,IAAI,QAAQ,CAAC,iBAAiB,GAAG,CAAC,KAAK,EAAE,CAAC;QACnE,QAAQ,CAAC,IAAI,CACX,0BAA0B,OAAO,CAAC,WAAW,EAAE,WAAW,OAAO,CAAC,WAAW,EAAE,aAAa,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,iBAAiB,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,uBAAuB,CACzK,CAAC;IACJ,CAAC;IAED,iCAAiC;IACjC,IAAI,QAAQ,CAAC,QAAQ,IAAI,EAAE,IAAI,QAAQ,CAAC,QAAQ,IAAI,EAAE,IAAI,QAAQ,CAAC,GAAG,GAAG,CAAC,EAAE,CAAC;QAC3E,MAAM,IAAI,GAAG,CAAC,CAAC,QAAQ,CAAC,GAAG,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;QAClE,IAAI,IAAI,GAAG,EAAE,EAAE,CAAC;YACd,QAAQ,CAAC,IAAI,CACX,oBAAoB,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,sDAAsD,CAC1F,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO;QACL,OAAO;QACP,OAAO;QACP,IAAI;QACJ,mBAAmB;QACnB,QAAQ;QACR,eAAe,EAAE,QAAQ;YACvB,CAAC,CAAC;gBACE,OAAO,EAAE,QAAQ,CAAC,aAAa;gBAC/B,OAAO,EAAE,QAAQ,CAAC,aAAa;gBAC/B,GAAG,EAAE,QAAQ,CAAC,GAAG;gBACjB,IAAI,EAAE,QAAQ,CAAC,GAAG,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,GAAG,UAAU,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;aAC/E;YACH,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,EAAE;QAClE,gBAAgB,EAAE,SAAS;YACzB,CAAC,CAAC;gBACE,OAAO,EAAE,SAAS,CAAC,aAAa;gBAChC,OAAO,EAAE,SAAS,CAAC,aAAa;gBAChC,GAAG,EAAE,SAAS,CAAC,GAAG;aACnB;YACH,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,EAAE;KAC1D,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,sBAAsB,CAAC,QAAuB;IAC5D,MAAM,OAAO,GAAiB,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;IACnE,MAAM,YAAY,GAAwB,EAAE,CAAC;IAE7C,oBAAoB;IACpB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACxC,KAAK,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC5C,MAAM,WAAW,GAAG,wBAAwB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;YAC/E,IAAI,WAAW,EAAE,CAAC;gBAChB,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YACjC,CAAC;QACH,CAAC;IACH,CAAC;IAED,+BAA+B;IAC/B,MAAM,kBAAkB,GAAG,YAAY;SACpC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACX,OAAO,EAAE,CAAC,CAAC,OAAO;QAClB,OAAO,EAAE,CAAC,CAAC,OAAO;QAClB,QAAQ,EAAE,CAAC,CAAC,mBAAmB;KAChC,CAAC,CAAC;SACF,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC;IAE3C,oBAAoB;IACpB,MAAM,QAAQ,GAAa,EAAE,CAAC;IAE9B,IAAI,kBAAkB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAClC,MAAM,GAAG,GAAG,kBAAkB,CAAC,CAAC,CAAC,CAAC;QAClC,QAAQ,CAAC,IAAI,CACX,0BAA0B,GAAG,CAAC,OAAO,CAAC,WAAW,EAAE,MAAM,GAAG,CAAC,OAAO,CAAC,WAAW,EAAE,eAAe,CAAC,GAAG,CAAC,QAAQ,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CACrI,CAAC;IACJ,CAAC;IAED,uBAAuB;IACvB,KAAK,MAAM,WAAW,IAAI,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;QACnD,QAAQ,CAAC,IAAI,CAAC,GAAG,WAAW,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACrD,CAAC;IAED,2BAA2B;IAC3B,MAAM,eAAe,GAAa,EAAE,CAAC;IAErC,yDAAyD;IACzD,IAAI,WAAW,GAA4C,IAAI,CAAC;IAChE,KAAK,MAAM,WAAW,IAAI,YAAY,EAAE,CAAC;QACvC,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACxC,IAAI,QAAQ,CAAC,QAAQ,IAAI,EAAE,IAAI,QAAQ,CAAC,iBAAiB,GAAG,CAAC,EAAE,CAAC;YAC9D,IAAI,CAAC,WAAW,IAAI,QAAQ,CAAC,iBAAiB,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC;gBACpE,WAAW,GAAG;oBACZ,IAAI,EAAE,GAAG,WAAW,CAAC,OAAO,CAAC,WAAW,EAAE,MAAM,WAAW,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE;oBACnF,MAAM,EAAE,QAAQ,CAAC,iBAAiB;iBACnC,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,WAAW,EAAE,CAAC;QAChB,eAAe,CAAC,IAAI,CAClB,6BAA6B,WAAW,CAAC,IAAI,iCAAiC,CAC/E,CAAC;IACJ,CAAC;IAED,8BAA8B;IAC9B,IAAI,YAAY,GAA4C,IAAI,CAAC;IACjE,KAAK,MAAM,WAAW,IAAI,YAAY,EAAE,CAAC;QACvC,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACxC,IAAI,QAAQ,CAAC,QAAQ,IAAI,EAAE,IAAI,QAAQ,CAAC,iBAAiB,GAAG,CAAC,EAAE,CAAC;YAC9D,IAAI,CAAC,YAAY,IAAI,QAAQ,CAAC,iBAAiB,GAAG,YAAY,CAAC,MAAM,EAAE,CAAC;gBACtE,YAAY,GAAG;oBACb,IAAI,EAAE,GAAG,WAAW,CAAC,OAAO,CAAC,WAAW,EAAE,MAAM,WAAW,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE;oBACnF,MAAM,EAAE,QAAQ,CAAC,iBAAiB;iBACnC,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,YAAY,EAAE,CAAC;QACjB,eAAe,CAAC,IAAI,CAClB,WAAW,YAAY,CAAC,IAAI,mCAAmC,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CACjH,CAAC;IACJ,CAAC;IAED,OAAO;QACL,YAAY;QACZ,kBAAkB;QAClB,QAAQ;QACR,eAAe;KAChB,CAAC;AACJ,CAAC;AAED,gFAAgF;AAChF,oBAAoB;AACpB,gFAAgF;AAEhF;;GAEG;AACH,MAAM,UAAU,2BAA2B,CAAC,MAAyB;IACnE,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,KAAK,CAAC,IAAI,CAAC,sCAAsC,CAAC,CAAC;IACnD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CACR,4FAA4F,CAC7F,CAAC;IACF,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAEf,eAAe;IACf,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/B,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;QAC/B,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;YACtC,KAAK,CAAC,IAAI,CAAC,KAAK,OAAO,EAAE,CAAC,CAAC;QAC7B,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjB,CAAC;IAED,kBAAkB;IAClB,IAAI,MAAM,CAAC,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtC,KAAK,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;QAClC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,eAAe,EAAE,CAAC;YACzC,KAAK,CAAC,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC;QACzB,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjB,CAAC;IAED,+BAA+B;IAC/B,IAAI,MAAM,CAAC,kBAAkB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzC,KAAK,CAAC,IAAI,CAAC,kCAAkC,CAAC,CAAC;QAC/C,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,wCAAwC,CAAC,CAAC;QACrD,KAAK,CAAC,IAAI,CAAC,uCAAuC,CAAC,CAAC;QACpD,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,kBAAkB,EAAE,CAAC;YAC/C,KAAK,CAAC,IAAI,CACR,KAAK,MAAM,CAAC,OAAO,CAAC,WAAW,EAAE,MAAM,MAAM,CAAC,OAAO,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CACjH,CAAC;QACJ,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjB,CAAC;IAED,sCAAsC;IACtC,MAAM,eAAe,GAAG,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACxD,KAAK,MAAM,WAAW,IAAI,eAAe,EAAE,CAAC;QAC1C,KAAK,CAAC,IAAI,CAAC,OAAO,WAAW,CAAC,OAAO,CAAC,WAAW,EAAE,MAAM,WAAW,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;QAC9F,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,YAAY,WAAW,CAAC,OAAO,CAAC,WAAW,EAAE,wBAAwB,WAAW,CAAC,OAAO,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;QACvH,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;QAEhC,MAAM,SAAS,GAAG,CAAC,QAAQ,WAAW,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,EAAE,YAAY,EAAE,QAAQ,WAAW,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;QAC3H,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3B,MAAM,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClC,MAAM,GAAG,GAAG;gBACV,SAAS,CAAC,CAAC,CAAC;gBACZ,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;gBACpB,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;gBACpB,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;aACrB,CAAC;YACF,KAAK,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACvC,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAEf,IAAI,WAAW,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACpC,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;YAC5B,KAAK,MAAM,OAAO,IAAI,WAAW,CAAC,QAAQ,EAAE,CAAC;gBAC3C,KAAK,CAAC,IAAI,CAAC,KAAK,OAAO,EAAE,CAAC,CAAC;YAC7B,CAAC;YACD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACjB,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,SAAS,UAAU,CAAC,IAAqB;IACvC,IAAI,IAAI,CAAC,QAAQ,GAAG,EAAE;QAAE,OAAO,GAAG,CAAC,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,QAAQ,GAAG,CAAC;IACtF,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;IAC/C,OAAO,GAAG,CAAC,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,SAAS,EAAE,CAAC;AACxD,CAAC"}
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
*
|
|
10
10
|
* @author Kanmi Obasa <i@kanmiobasa.com>
|
|
11
11
|
*/
|
|
12
|
-
import type { ConversionCurve } from './conversion-curve.js';
|
|
12
|
+
import type { ConversionCurve, PerformanceMetric } from './conversion-curve.js';
|
|
13
13
|
export interface OpportunityScenario {
|
|
14
14
|
/** Descriptive name for the scenario */
|
|
15
15
|
name: string;
|
|
@@ -40,7 +40,7 @@ export interface OpportunityScenario {
|
|
|
40
40
|
}
|
|
41
41
|
export interface OpportunityReport {
|
|
42
42
|
/** The metric analyzed */
|
|
43
|
-
metric:
|
|
43
|
+
metric: PerformanceMetric;
|
|
44
44
|
/** Analysis period */
|
|
45
45
|
period: {
|
|
46
46
|
days: number;
|
|
@@ -82,26 +82,14 @@ export interface OpportunityConfig {
|
|
|
82
82
|
*/
|
|
83
83
|
export declare function calculateOpportunity(curve: ConversionCurve, config: OpportunityConfig): OpportunityReport;
|
|
84
84
|
/**
|
|
85
|
-
* Calculate opportunity for all
|
|
85
|
+
* Calculate opportunity for all performance metrics.
|
|
86
86
|
*/
|
|
87
|
-
export declare function calculateAllOpportunities(curves:
|
|
88
|
-
lcp: ConversionCurve;
|
|
89
|
-
inp: ConversionCurve;
|
|
90
|
-
cls: ConversionCurve;
|
|
91
|
-
}, config: OpportunityConfig): {
|
|
92
|
-
lcp: OpportunityReport;
|
|
93
|
-
inp: OpportunityReport;
|
|
94
|
-
cls: OpportunityReport;
|
|
95
|
-
};
|
|
87
|
+
export declare function calculateAllOpportunities(curves: Record<PerformanceMetric, ConversionCurve>, config: OpportunityConfig): Record<PerformanceMetric, OpportunityReport>;
|
|
96
88
|
/**
|
|
97
89
|
* Get the single highest-impact opportunity across all metrics.
|
|
98
90
|
*/
|
|
99
|
-
export declare function getTopOpportunity(opportunities: {
|
|
100
|
-
|
|
101
|
-
inp: OpportunityReport;
|
|
102
|
-
cls: OpportunityReport;
|
|
103
|
-
}): {
|
|
104
|
-
metric: 'lcp' | 'inp' | 'cls';
|
|
91
|
+
export declare function getTopOpportunity(opportunities: Record<string, OpportunityReport>): {
|
|
92
|
+
metric: PerformanceMetric;
|
|
105
93
|
scenario: OpportunityScenario;
|
|
106
94
|
} | null;
|
|
107
95
|
//# sourceMappingURL=opportunity-calculator.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"opportunity-calculator.d.ts","sourceRoot":"","sources":["../../src/empirical/opportunity-calculator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAoB,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"opportunity-calculator.d.ts","sourceRoot":"","sources":["../../src/empirical/opportunity-calculator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAoB,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAMlG,MAAM,WAAW,mBAAmB;IAClC,wCAAwC;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,iEAAiE;IACjE,SAAS,EAAE,MAAM,CAAC;IAClB,2CAA2C;IAC3C,aAAa,EAAE,MAAM,CAAC;IACtB,iDAAiD;IACjD,aAAa,EAAE,MAAM,CAAC;IACtB,qCAAqC;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,qCAAqC;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,4CAA4C;IAC5C,SAAS,EAAE,MAAM,CAAC;IAClB,sDAAsD;IACtD,oBAAoB,EAAE,MAAM,CAAC;IAC7B,8DAA8D;IAC9D,0BAA0B,EAAE,MAAM,CAAC;IACnC,gDAAgD;IAChD,mBAAmB,EAAE,MAAM,CAAC;IAC5B,uDAAuD;IACvD,4BAA4B,EAAE,MAAM,CAAC;IACrC,+BAA+B;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,6BAA6B;IAC7B,UAAU,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;CACvC;AAED,MAAM,WAAW,iBAAiB;IAChC,0BAA0B;IAC1B,MAAM,EAAE,iBAAiB,CAAC;IAC1B,sBAAsB;IACtB,MAAM,EAAE;QACN,IAAI,EAAE,MAAM,CAAC;QACb,cAAc,EAAE,MAAM,CAAC;KACxB,CAAC;IACF,+CAA+C;IAC/C,SAAS,EAAE,mBAAmB,EAAE,CAAC;IACjC,qDAAqD;IACrD,cAAc,EAAE;QACd,QAAQ,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;QACpC,SAAS,EAAE,MAAM,CAAC;QAClB,mBAAmB,EAAE,MAAM,CAAC;QAC5B,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,sCAAsC;IACtC,aAAa,EAAE;QACb,cAAc,EAAE,MAAM,CAAC;QACvB,WAAW,EAAE,MAAM,CAAC;QACpB,WAAW,EAAE,MAAM,CAAC;QACpB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;CACH;AAED,MAAM,WAAW,iBAAiB;IAChC,8DAA8D;IAC9D,UAAU,EAAE,MAAM,CAAC;IACnB,oEAAoE;IACpE,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,+DAA+D;IAC/D,sBAAsB,CAAC,EAAE,MAAM,CAAC;CACjC;AAQD;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,eAAe,EACtB,MAAM,EAAE,iBAAiB,GACxB,iBAAiB,CA6CnB;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,MAAM,CAAC,iBAAiB,EAAE,eAAe,CAAC,EAClD,MAAM,EAAE,iBAAiB,GACxB,MAAM,CAAC,iBAAiB,EAAE,iBAAiB,CAAC,CAW9C;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,GAC/C;IAAE,MAAM,EAAE,iBAAiB,CAAC;IAAC,QAAQ,EAAE,mBAAmB,CAAA;CAAE,GAAG,IAAI,CAoBrE"}
|
|
@@ -54,13 +54,18 @@ export function calculateOpportunity(curve, config) {
|
|
|
54
54
|
};
|
|
55
55
|
}
|
|
56
56
|
/**
|
|
57
|
-
* Calculate opportunity for all
|
|
57
|
+
* Calculate opportunity for all performance metrics.
|
|
58
58
|
*/
|
|
59
59
|
export function calculateAllOpportunities(curves, config) {
|
|
60
60
|
return {
|
|
61
61
|
lcp: calculateOpportunity(curves.lcp, config),
|
|
62
|
+
fcp: calculateOpportunity(curves.fcp, config),
|
|
62
63
|
inp: calculateOpportunity(curves.inp, config),
|
|
63
64
|
cls: calculateOpportunity(curves.cls, config),
|
|
65
|
+
ttfb: calculateOpportunity(curves.ttfb, config),
|
|
66
|
+
tti: calculateOpportunity(curves.tti, config),
|
|
67
|
+
onload: calculateOpportunity(curves.onload, config),
|
|
68
|
+
page_size: calculateOpportunity(curves.page_size, config),
|
|
64
69
|
};
|
|
65
70
|
}
|
|
66
71
|
/**
|
|
@@ -211,16 +216,29 @@ function getDefaultTargets(metric) {
|
|
|
211
216
|
switch (metric) {
|
|
212
217
|
case 'lcp':
|
|
213
218
|
return [2500, 3000, 4000]; // Good threshold, mid, poor threshold
|
|
219
|
+
case 'fcp':
|
|
220
|
+
return [1800, 2400, 3000]; // Good < 1.8s, needs improvement < 3s
|
|
214
221
|
case 'inp':
|
|
215
222
|
return [200, 300, 500];
|
|
216
223
|
case 'cls':
|
|
217
224
|
return [100, 150, 250]; // Scaled by 1000
|
|
225
|
+
case 'ttfb':
|
|
226
|
+
return [800, 1200, 1800];
|
|
227
|
+
case 'tti':
|
|
228
|
+
return [3800, 5500, 7300]; // Good < 3.8s, needs improvement < 7.3s
|
|
229
|
+
case 'onload':
|
|
230
|
+
return [3000, 4500, 6000];
|
|
231
|
+
case 'page_size':
|
|
232
|
+
return [3000, 5000, 8000]; // KB
|
|
218
233
|
}
|
|
219
234
|
}
|
|
220
235
|
function formatTargetLabel(targetMs, metric) {
|
|
221
236
|
if (metric === 'cls') {
|
|
222
237
|
return (targetMs / 1000).toFixed(2);
|
|
223
238
|
}
|
|
239
|
+
if (metric === 'page_size') {
|
|
240
|
+
return `${(targetMs / 1000).toFixed(1)}MB`;
|
|
241
|
+
}
|
|
224
242
|
if (targetMs >= 1000) {
|
|
225
243
|
return `${(targetMs / 1000).toFixed(1)}s`;
|
|
226
244
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"opportunity-calculator.js","sourceRoot":"","sources":["../../src/empirical/opportunity-calculator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAwEH,gFAAgF;AAChF,yBAAyB;AACzB,gFAAgF;AAEhF,MAAM,mBAAmB,GAAG,EAAE,CAAC;AAE/B;;;;;;;;GAQG;AACH,MAAM,UAAU,oBAAoB,CAClC,KAAsB,EACtB,MAAyB;IAEzB,MAAM,EACJ,UAAU,EACV,sBAAsB,GAAG,EAAE,GAC5B,GAAG,MAAM,CAAC;IAEX,MAAM,aAAa,GAAG,mBAAmB,GAAG,UAAU,CAAC;IACvD,MAAM,OAAO,GAAG,MAAM,CAAC,gBAAgB,IAAI,iBAAiB,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAE3E,MAAM,SAAS,GAA0B,EAAE,CAAC;IAE5C,KAAK,MAAM,QAAQ,IAAI,OAAO,EAAE,CAAC;QAC/B,MAAM,QAAQ,GAAG,yBAAyB,CACxC,KAAK,EACL,QAAQ,EACR,aAAa,EACb,sBAAsB,CACvB,CAAC;QAEF,IAAI,QAAQ,EAAE,CAAC;YACb,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC;IAED,2BAA2B;IAC3B,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,4BAA4B,GAAG,CAAC,CAAC,4BAA4B,CAAC,CAAC;IAE1F,0BAA0B;IAC1B,MAAM,cAAc,GAAG,sBAAsB,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IAEhE,OAAO;QACL,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,MAAM,EAAE;YACN,IAAI,EAAE,UAAU;YAChB,cAAc,EAAE,aAAa;SAC9B;QACD,SAAS;QACT,cAAc;QACd,aAAa,EAAE;YACb,cAAc,EAAE,KAAK,CAAC,OAAO,CAAC,cAAc;YAC5C,WAAW,EAAE,KAAK,CAAC,OAAO,CAAC,WAAW;YACtC,WAAW,EAAE,KAAK,CAAC,OAAO,CAAC,WAAW;YACtC,SAAS,EAAE,KAAK,CAAC,OAAO,CAAC,SAAS;SACnC;KACF,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,yBAAyB,CACvC,
|
|
1
|
+
{"version":3,"file":"opportunity-calculator.js","sourceRoot":"","sources":["../../src/empirical/opportunity-calculator.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*
|
|
8
8
|
* @author Kanmi Obasa <i@kanmiobasa.com>
|
|
9
9
|
*/
|
|
10
|
-
import type { ConversionCurve } from './conversion-curve.js';
|
|
10
|
+
import type { ConversionCurve, PerformanceMetric } from './conversion-curve.js';
|
|
11
11
|
import type { OpportunityReport } from './opportunity-calculator.js';
|
|
12
12
|
export interface ReportConfig {
|
|
13
13
|
clientName?: string;
|
|
@@ -19,16 +19,8 @@ export interface ReportConfig {
|
|
|
19
19
|
includeRawCurve?: boolean;
|
|
20
20
|
}
|
|
21
21
|
export interface FullReport {
|
|
22
|
-
curves:
|
|
23
|
-
|
|
24
|
-
inp: ConversionCurve;
|
|
25
|
-
cls: ConversionCurve;
|
|
26
|
-
};
|
|
27
|
-
opportunities: {
|
|
28
|
-
lcp: OpportunityReport;
|
|
29
|
-
inp: OpportunityReport;
|
|
30
|
-
cls: OpportunityReport;
|
|
31
|
-
};
|
|
22
|
+
curves: Record<PerformanceMetric, ConversionCurve>;
|
|
23
|
+
opportunities: Record<PerformanceMetric, OpportunityReport>;
|
|
32
24
|
}
|
|
33
25
|
/**
|
|
34
26
|
* Generate a complete markdown report.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../src/empirical/report.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../src/empirical/report.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAChF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAMrE,MAAM,WAAW,YAAY;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE;QACN,KAAK,EAAE,MAAM,CAAC;QACd,GAAG,EAAE,MAAM,CAAC;QACZ,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;IACF,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC,iBAAiB,EAAE,eAAe,CAAC,CAAC;IACnD,aAAa,EAAE,MAAM,CAAC,iBAAiB,EAAE,iBAAiB,CAAC,CAAC;CAC7D;AAMD;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,YAAY,GAAG,MAAM,CA+F7E"}
|
package/dist/empirical/report.js
CHANGED
|
@@ -32,15 +32,18 @@ export function generateReport(data, config) {
|
|
|
32
32
|
lines.push('');
|
|
33
33
|
lines.push(generateExecutiveSummary(data.opportunities));
|
|
34
34
|
lines.push('');
|
|
35
|
+
// All performance metrics
|
|
36
|
+
const ALL_METRICS = ['lcp', 'fcp', 'inp', 'cls', 'ttfb', 'tti', 'onload', 'page_size'];
|
|
35
37
|
// Measured Conversion Curves
|
|
36
38
|
lines.push('## Measured Conversion Rates');
|
|
37
39
|
lines.push('');
|
|
38
40
|
lines.push('These are the **actual conversion rates** measured at each performance bucket from your session data:');
|
|
39
41
|
lines.push('');
|
|
40
|
-
for (const metric of
|
|
42
|
+
for (const metric of ALL_METRICS) {
|
|
41
43
|
const curve = data.curves[metric];
|
|
42
44
|
if (curve.buckets.length > 0) {
|
|
43
|
-
|
|
45
|
+
const metricLabel = metric === 'page_size' ? 'Page Size' : metric.toUpperCase();
|
|
46
|
+
lines.push(`### ${metricLabel} Conversion Curve`);
|
|
44
47
|
lines.push('');
|
|
45
48
|
lines.push(generateCurveTable(curve));
|
|
46
49
|
lines.push('');
|
|
@@ -49,11 +52,12 @@ export function generateReport(data, config) {
|
|
|
49
52
|
// Revenue Opportunities
|
|
50
53
|
lines.push('## Revenue Opportunities');
|
|
51
54
|
lines.push('');
|
|
52
|
-
const allOpportunities =
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
55
|
+
const allOpportunities = ALL_METRICS
|
|
56
|
+
.map((metric) => ({
|
|
57
|
+
metric: metric === 'page_size' ? 'Page Size' : metric.toUpperCase(),
|
|
58
|
+
report: data.opportunities[metric],
|
|
59
|
+
}))
|
|
60
|
+
.filter((o) => o.report.scenarios.length > 0);
|
|
57
61
|
if (allOpportunities.length === 0) {
|
|
58
62
|
lines.push('No significant opportunities detected. Your performance distribution shows minimal CVR variation across buckets.');
|
|
59
63
|
lines.push('');
|