ga4_organic_search_performance
Retrieve organic search traffic metrics: sessions, users, engagement, and conversions. Break down results by landing page, source, country, or device for SEO analysis.
Instructions
SEO: sessions/users/engagement/conversions for Organic Search traffic, broken down by landing page (default), source, country, or device.
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 | |
| breakdown | No | Dimension to break organic traffic down by | landingPage |
Implementation Reference
- src/index.ts:55-62 (registration)Registration of the ga4_organic_search_performance tool via server.tool(), linking it to organicSearchSchema and the organicSearchPerformance handler.
server.tool( "ga4_organic_search_performance", "SEO: sessions/users/engagement/conversions for Organic Search traffic, broken down by landing page (default), source, country, or device.", organicSearchSchema, async (args) => { try { return ok(await organicSearchPerformance(args)); } catch (e) { return err(e); } } ); - src/tools/seo.ts:4-13 (schema)Zod schema defining the input parameters for the organic search performance tool: start_date, end_date, property_id, limit, and breakdown (with enum options).
export const organicSearchSchema = { start_date: z.string().default(DEFAULT_START).describe("Start date: YYYY-MM-DD, NdaysAgo, yesterday, or today"), end_date: z.string().default(DEFAULT_END).describe("End date: YYYY-MM-DD, NdaysAgo, yesterday, or today"), property_id: z.string().optional().describe("Override GA4_PROPERTY_ID env var for this call"), limit: z.number().int().positive().max(10000).default(50).describe("Max rows to return"), breakdown: z .enum(["landingPage", "sessionSource", "pagePath", "country", "deviceCategory"]) .default("landingPage") .describe("Dimension to break organic traffic down by"), }; - src/tools/seo.ts:15-51 (handler)Main handler function that calls GA4 Data API runReport with Organic Search dimension filter, returning rows with dimension and metric values.
export async function organicSearchPerformance(args: z.infer<z.ZodObject<typeof organicSearchSchema>>) { const [res] = await getClient().runReport({ property: getProperty(args.property_id), dateRanges: [{ startDate: args.start_date, endDate: args.end_date }], dimensions: [{ name: args.breakdown }], metrics: [ { name: "sessions" }, { name: "totalUsers" }, { name: "newUsers" }, { name: "engagementRate" }, { name: "averageSessionDuration" }, { name: "conversions" }, { name: "keyEvents" }, ], dimensionFilter: { filter: { fieldName: "sessionDefaultChannelGroup", stringFilter: { value: "Organic Search" }, }, }, orderBys: [{ metric: { metricName: "sessions" }, desc: true }], limit: args.limit as unknown as number, }); 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 }; }