ga4_landing_page_performance
Analyze top landing pages by sessions, engagement, and conversions. Optionally filter by channel like Organic Search or Paid Search to evaluate performance.
Instructions
Top landing pages by sessions/engagement/conversions. Optional channel filter (e.g. 'Organic Search', 'Paid Search').
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| start_date | No | Start date: YYYY-MM-DD, NdaysAgo, yesterday, or today | 28daysAgo |
| end_date | No | End date: YYYY-MM-DD, NdaysAgo, yesterday, or today | yesterday |
| property_id | No | Override GA4_PROPERTY_ID env var for this call | |
| limit | No | Max rows to return | |
| channel | No | Optional sessionDefaultChannelGroup filter, e.g. 'Organic Search', 'Paid Search' |
Implementation Reference
- src/index.ts:91-98 (registration)Registration of the 'ga4_landing_page_performance' tool with the MCP server, including its description and schema reference.
server.tool( "ga4_landing_page_performance", "Top landing pages by sessions/engagement/conversions. Optional channel filter (e.g. 'Organic Search', 'Paid Search').", landingPageSchema, async (args) => { try { return ok(await landingPagePerformance(args)); } catch (e) { return err(e); } } ); - src/tools/reports.ts:72-75 (schema)Zod schema for landing_page_performance: date range params with optional channel filter.
export const landingPageSchema = { ...dateRange, channel: z.string().optional().describe("Optional sessionDefaultChannelGroup filter, e.g. 'Organic Search', 'Paid Search'"), }; - src/tools/reports.ts:77-97 (handler)Handler function that queries GA4 for top landing pages by sessions/engagement/conversions, with optional channel group filter.
export async function landingPagePerformance(args: z.infer<z.ZodObject<typeof landingPageSchema>>) { const [res] = await getClient().runReport({ property: getProperty(args.property_id), dateRanges: toDateRange(args.start_date, args.end_date), dimensions: [{ name: "landingPage" }, { name: "sessionDefaultChannelGroup" }], metrics: [ { name: "sessions" }, { name: "totalUsers" }, { name: "engagementRate" }, { name: "averageSessionDuration" }, { name: "conversions" }, { name: "keyEvents" }, ], dimensionFilter: args.channel ? { filter: { fieldName: "sessionDefaultChannelGroup", stringFilter: { value: args.channel } } } : undefined, orderBys: [{ metric: { metricName: "sessions" }, desc: true }], limit: args.limit as unknown as number, }); return formatReport(res); } - src/tools/reports.ts:15-29 (helper)Helper function formatReport transforms GA4 API response into a clean rows/rowCount format used by the handler.
function formatReport(res: any) { const rows = (res.rows ?? []).map((r: any) => { const out: Record<string, string | number> = {}; (res.dimensionHeaders ?? []).forEach((h: any, i: number) => { out[h.name] = r.dimensionValues?.[i]?.value ?? ""; }); (res.metricHeaders ?? []).forEach((h: any, i: number) => { const v = r.metricValues?.[i]?.value ?? "0"; const n = Number(v); out[h.name] = Number.isFinite(n) ? n : v; }); return out; }); return { rowCount: res.rowCount ?? rows.length, rows }; }