ga4_google_ads_performance
Retrieve Google Ads campaign, ad group, and keyword performance metrics from GA4, including impressions, clicks, cost, CPC, conversions, and ROAS. Requires linked Google Ads and GA4 account.
Instructions
Paid: Google Ads campaign × ad group × keyword performance (impressions, clicks, cost, CPC, conversions, ROAS). Requires Google Ads ↔ GA4 link.
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 |
Implementation Reference
- src/tools/paid.ts:101-124 (handler)The handler function that executes GA4 Google Ads performance report logic. Calls runReport with Google Ads dimensions (campaign, ad group, keyword) and metrics (impressions, clicks, cost, CPC, sessions, key events, revenue, ROAS). No dimension filter (applies to all linked Google Ads data).
export async function googleAdsPerformance(args: z.infer<z.ZodObject<typeof googleAdsSchema>>) { const [res] = await getClient().runReport({ property: getProperty(args.property_id), dateRanges: [{ startDate: args.start_date, endDate: args.end_date }], dimensions: [ { name: "googleAdsCampaignName" }, { name: "googleAdsAdGroupName" }, { name: "googleAdsKeyword" }, ], metrics: [ { name: "advertiserAdImpressions" }, { name: "advertiserAdClicks" }, { name: "advertiserAdCost" }, { name: "advertiserAdCostPerClick" }, { name: "sessions" }, { name: "keyEvents" }, { name: "totalRevenue" }, { name: "returnOnAdSpend" }, ], orderBys: [{ metric: { metricName: "advertiserAdCost" }, desc: true }], limit: args.limit as unknown as number, }); return formatReport(res); } - src/tools/paid.ts:99-99 (schema)Schema definition for googleAds tool. Extends common schema (start_date, end_date, property_id, limit) with no additional fields.
export const googleAdsSchema = { ...common }; - src/index.ts:82-89 (registration)Tool registration via server.tool() with name 'ga4_google_ads_performance', description, schema, and handler.
server.tool( "ga4_google_ads_performance", "Paid: Google Ads campaign × ad group × keyword performance (impressions, clicks, cost, CPC, conversions, ROAS). Requires Google Ads ↔ GA4 link.", googleAdsSchema, async (args) => { try { return ok(await googleAdsPerformance(args)); } catch (e) { return err(e); } } ); - src/tools/paid.ts:11-25 (helper)Formatting helper used by googleAdsPerformance to transform the GA4 API response into a clean row-based structure with typed metric values.
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 }; } - src/tools/paid.ts:4-9 (helper)Common schema fields shared by googleAdsSchema (start_date, end_date, property_id, limit).
const common = { 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"), };