import { getPropertyId, formatPropertyPath, executeReport } from "../../client.js";
import {
periodToDateRange,
getPreviousPeriod,
getPreviousYearPeriod,
getPeriodLabel,
} from "../../utils/date.js";
import { formatChange, formatMetricName } from "../../utils/format.js";
import type {
ComparePeriodInput,
ComparePeriodOutput,
MetricComparison,
DateRange,
} from "../../types.js";
/**
* 2つの期間を比較
*/
export async function comparePeriods(
input: ComparePeriodInput
): Promise<ComparePeriodOutput> {
const propertyId = getPropertyId(input.propertyId);
const property = formatPropertyPath(propertyId);
// 期間を決定
let period1: DateRange;
let period2: DateRange;
if (input.comparisonType === "custom") {
if (!input.period1 || !input.period2) {
throw new Error(
"custom 比較タイプの場合は period1 と period2 を指定してください"
);
}
period1 = input.period1;
period2 = input.period2;
} else {
const period = input.period || "7days";
period1 = periodToDateRange(period);
if (input.comparisonType === "previousYear") {
period2 = getPreviousYearPeriod(period1);
} else {
// previousPeriod
period2 = getPreviousPeriod(period1);
}
}
// 比較するメトリクス
const metrics = input.metrics || [
"screenPageViews",
"totalUsers",
"sessions",
];
// 期間1のデータ取得
const response1 = await executeReport({
property,
dateRanges: [period1],
metrics: metrics.map((name) => ({ name })),
});
// 期間2のデータ取得
const response2 = await executeReport({
property,
dateRanges: [period2],
metrics: metrics.map((name) => ({ name })),
});
// 結果を比較
const comparison: MetricComparison[] = [];
const metricValues1 = response1.totals?.[0]?.metricValues || [];
const metricValues2 = response2.totals?.[0]?.metricValues || [];
for (let i = 0; i < metrics.length; i++) {
const metricName = metrics[i];
const value1 = metricValues1[i]?.value
? parseFloat(metricValues1[i].value!)
: 0;
const value2 = metricValues2[i]?.value
? parseFloat(metricValues2[i].value!)
: 0;
const changeData = formatChange(value1, value2);
comparison.push({
metric: formatMetricName(metricName),
period1Value: Math.round(value1),
period2Value: Math.round(value2),
...changeData,
});
}
return {
period1: { ...period1, label: getPeriodLabel(period1) },
period2: { ...period2, label: getPeriodLabel(period2) },
comparison,
};
}