import { getPropertyId, formatPropertyPath, executeReport } from "../../client.js";
import { periodToDateRange } from "../../utils/date.js";
import { calculatePercentage } from "../../utils/percentage.js";
import type {
GetSearchTermsInput,
GetSearchTermsOutput,
SearchTerm,
} from "../../types.js";
/**
* サイト内検索キーワードの分析
*
* 注意: このツールはGA4でサイト内検索が設定されている場合のみ動作します。
* サイト内検索の設定がない場合は空の結果が返されます。
*/
export async function getSearchTerms(
input: GetSearchTermsInput
): Promise<GetSearchTermsOutput> {
const propertyId = getPropertyId(input.propertyId);
const property = formatPropertyPath(propertyId);
const dateRange = periodToDateRange(input.period);
const limit = input.limit || 20;
// サイト内検索キーワードを取得
// GA4では searchTerm ディメンションを使用
const response = await executeReport({
property,
dateRanges: [dateRange],
dimensions: [{ name: "searchTerm" }],
metrics: [
{ name: "eventCount" },
{ name: "totalUsers" },
{ name: "screenPageViews" },
],
orderBys: [{ metric: { metricName: "eventCount" }, desc: true }],
limit,
// view_search_results イベントでフィルター
dimensionFilter: {
filter: {
fieldName: "eventName",
stringFilter: {
matchType: "EXACT",
value: "view_search_results",
},
},
},
});
// 合計イベント数を取得(検索離脱率計算用)
const totalSearches =
response.totals?.[0]?.metricValues?.[0]?.value
? parseFloat(response.totals[0].metricValues[0].value)
: 0;
const searchTerms: SearchTerm[] = [];
for (const row of response.rows || []) {
const term = row.dimensionValues?.[0]?.value || "";
const metricValues = row.metricValues || [];
const getValue = (index: number): number => {
const value = metricValues[index]?.value;
return value ? parseFloat(value) : 0;
};
const searchCount = Math.round(getValue(0));
const uniqueSearches = Math.round(getValue(1));
const resultsPageviews = Math.round(getValue(2));
// 検索離脱率: 結果ページを見た後に離脱した割合(概算)
// 正確な計算には追加のイベント分析が必要
const searchExitRate = calculatePercentage(
searchCount - resultsPageviews,
searchCount
);
searchTerms.push({
term,
searchCount,
uniqueSearches,
resultsPageviews,
searchExitRate,
});
}
return { searchTerms };
}