Get AdWords spend over time
grips_get_adwordsGet monthly paid-media spend, ad clicks, and CPC for up to 50 domains. Analyze paid-search cost trends, auction inflation, and total investment over a custom date range.
Instructions
Returns paid-media spend, ad clicks, and CPC for one or more domains — monthly timeseries plus an aggregated roll-up. Use this to evaluate paid-spend trends, auction-cost inflation, or total investment in paid search.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| domains | Yes | One or more domains (e.g. ['adidas.com', 'nike.com']). Protocol and trailing slash are stripped automatically. | |
| date_from | Yes | Start of the reporting window, inclusive, as YYYY-MM-DD. Example: '2024-01-01'. | |
| date_to | Yes | End of the reporting window, inclusive, as YYYY-MM-DD. Example: '2024-12-31'. | |
| country | No | Optional country filter. Defaults to the server's GRIPS_DEFAULT_COUNTRY (usually 'US'). | |
| format | No | Response format. 'markdown' is human-readable; 'json' is machine-parseable. | markdown |
Implementation Reference
- src/tools/adwords.ts:43-121 (handler)Main handler function for grips_get_adwords. Calls the Grips API with ADWORDS_QUERY, processes timeseries and aggregated results, and returns either JSON or markdown.
export async function runAdwords( client: GripsApiClient, args: AdwordsInput, defaultCountry: string, ): Promise<string> { const country = args.country ?? defaultCountry; const variables = buildFilters({ domains: args.domains, date_from: args.date_from, date_to: args.date_to, country, }); let raw: { timeseries?: unknown; aggregated?: unknown } = {}; try { raw = await client.query<{ timeseries?: unknown; aggregated?: unknown }>({ query: ADWORDS_QUERY, variables, }); } catch (err) { const msg = formatUpstreamError(err); const hint = errorHint(err); return `Error: ${msg}${hint ? `\n\nHint: ${hint}` : ""}`; } const rows = toArray<AdwordsTimeseriesRow>(raw.timeseries).map((r) => ({ ...r, date: normalizeDate(r?.date), })); // Grips returns `aggregated` as a single object (not an array) for the // adwords endpoint — use toObject, not toArray. const agg = toObject<AdwordsAggregated>(raw.aggregated); if (rows.length === 0 && Object.keys(agg).length === 0) { return `**Grips AdWords spend — ${args.domains.join(", ")} (${country}, ${args.date_from} → ${args.date_to})**\n\n_No paid-search data returned by Grips for this filter set. The domain may not be running paid search, or may not be covered by Grips for this country/window._`; } if (args.format === "json") { return toJson({ domains: args.domains, country, date_from: args.date_from, date_to: args.date_to, timeseries: rows.map((r) => ({ date: r.date, adcost: safeNumberOrNull(r.adcost), adclicks: safeNumberOrNull(r.adclicks), cpc: safeNumberOrNull(r.cpc), })), aggregated: { adcost: safeNumberOrNull(agg.adcost), adclicks: safeNumberOrNull(agg.adclicks), cpc: safeNumberOrNull(agg.cpc), }, }); } const tsTable = toMarkdownTable( rows.map((r) => ({ Date: r.date, "Ad Cost": formatCurrency(r.adcost), "Ad Clicks": formatInt(r.adclicks), CPC: formatCurrency(r.cpc), })), ); const aggTable = toMarkdownTable([ { "Ad Cost (total)": formatCurrency(agg.adcost), "Ad Clicks (total)": formatInt(agg.adclicks), "CPC (avg)": formatCurrency(agg.cpc), }, ]); const header = `**Grips AdWords spend — ${args.domains.join(", ")} (${country}, ${args.date_from} → ${args.date_to})**`; return truncateIfNeeded( `${header}\n\n### Aggregated\n\n${aggTable}\n\n### Monthly timeseries\n\n${tsTable}`, ); } - src/index.ts:103-112 (registration)Tool registration in the MCP server using adwordsToolDef.name ('grips_get_adwords').
server.registerTool( adwordsToolDef.name, { title: adwordsToolDef.title, description: adwordsToolDef.description, inputSchema: adwordsToolDef.inputSchema, annotations: adwordsToolDef.annotations, }, async (args) => asText(await runAdwords(client, args as any, defaultCountry)), ); - src/schemas/common.ts:41-55 (schema)Input schema definition (baseFilterFields) used by grips_get_adwords. Defines domains, date_from, date_to, country, and format fields.
export const baseFilterFields = { domains: domainsArray.describe( "One or more domains (e.g. ['adidas.com', 'nike.com']). Protocol and trailing slash are stripped automatically.", ), date_from: isoDate.describe( "Start of the reporting window, inclusive, as YYYY-MM-DD. Example: '2024-01-01'.", ), date_to: isoDate.describe( "End of the reporting window, inclusive, as YYYY-MM-DD. Example: '2024-12-31'.", ), country: countryEnum .optional() .describe("Optional country filter. Defaults to the server's GRIPS_DEFAULT_COUNTRY (usually 'US')."), format: outputFormat, }; - src/tools/adwords.ts:26-41 (schema)Typed input schema (z.object wrapping baseFilterFields) and exported tool definition with name 'grips_get_adwords'.
export const adwordsInputSchema = z.object(baseFilterFields); export type AdwordsInput = z.infer<typeof adwordsInputSchema>; export const adwordsToolDef = { name: "grips_get_adwords", title: "Get AdWords spend over time", description: "Returns paid-media spend, ad clicks, and CPC for one or more domains — monthly timeseries plus an aggregated roll-up. Use this to evaluate paid-spend trends, auction-cost inflation, or total investment in paid search.", inputSchema: baseFilterFields, annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true, }, }; - src/services/queries.ts:117-144 (helper)GraphQL query (ADWORDS_QUERY) used by the handler to fetch adwords timeseries and aggregated data from the Grips API.
export const ADWORDS_QUERY = ` input Date { gte: String! lte: String! } input OrArray { in: [String!] } input Filters { country: String domain: OrArray! date: Date! } query ii_transactional($filters: Filters) { timeseries: fetch(filters: $filters) { date(type: Array, sort_asc: date) { adcost: sum(a: adcost) adclicks: sum(a: adclicks) cpc: divide(a: adcost, by: adclicks) } } aggregated: fetch(filters: $filters) { adcost: sum(a: adcost) adclicks: sum(a: adclicks) cpc: divide(a: adcost, by: adclicks) } } `; - src/types.ts:62-75 (helper)TypeScript interfaces for AdwordsTimeseriesRow and AdwordsAggregated.
/** One monthly row from the adwords endpoint. */ export interface AdwordsTimeseriesRow { date?: string; adcost?: number | string | null; adclicks?: number | string | null; cpc?: number | string | null; [key: string]: unknown; } /** Aggregated totals for the adwords endpoint. */ export interface AdwordsAggregated { adcost?: number | string | null; adclicks?: number | string | null; cpc?: number | string | null;