diff --git a/services/experimentAnalysis.ts b/services/experimentAnalysis.ts index 651d538..a43f38c 100644 --- a/services/experimentAnalysis.ts +++ b/services/experimentAnalysis.ts @@ -40,6 +40,7 @@ interface ComputedWeeklyMetrics extends WeeklyMetrics { cvr: number; ctr: number; roas: number; + fraction?: number; } function getISOWeekStart(year: number, week: number): number { @@ -142,9 +143,39 @@ function splitPeriods( // We prioritize assigning to 'after' so that we capture all units happening // closely around the experiment dates for accurate reporting. if (overlapsAfter) { - after.push(w); + const overlapStart = Math.max(weekStartTs, startTs); + const overlapEnd = Math.min(weekEndTs, endTs); + const overlapFraction = Math.max(0, Math.min(1, (overlapEnd - overlapStart) / (7 * 86400000))); + + if (overlapFraction > 0) { + after.push({ + ...w, + units: w.units * overlapFraction, + revenue: w.revenue * overlapFraction, + sessions: w.sessions * overlapFraction, + cost: w.cost * overlapFraction, + clicks: w.clicks * overlapFraction, + impressions: w.impressions * overlapFraction, + fraction: overlapFraction + }); + } } else if (overlapsBefore) { - before.push(w); + const overlapStart = Math.max(weekStartTs, beforeStartTs); + const overlapEnd = Math.min(weekEndTs, beforeEndTs); + const overlapFraction = Math.max(0, Math.min(1, (overlapEnd - overlapStart) / (7 * 86400000))); + + if (overlapFraction > 0) { + before.push({ + ...w, + units: w.units * overlapFraction, + revenue: w.revenue * overlapFraction, + sessions: w.sessions * overlapFraction, + cost: w.cost * overlapFraction, + clicks: w.clicks * overlapFraction, + impressions: w.impressions * overlapFraction, + fraction: overlapFraction + }); + } } } @@ -154,7 +185,8 @@ function splitPeriods( function avgMetric(data: ComputedWeeklyMetrics[], metric: string): number { if (data.length === 0) return 0; const sum = data.reduce((s, w) => s + getMetricValue(w, metric), 0); - return sum / data.length; + const totalFraction = data.reduce((s, w) => s + (w.fraction || 1), 0); + return totalFraction > 0 ? sum / totalFraction : 0; } const METRICS = ['units', 'sessions', 'cvr', 'ctr', 'roas', 'revenue', 'acos'];