wordstat_get_dynamics
Retrieve historical search frequency trends for a keyword over daily, weekly, or monthly periods, optionally filtered by region and device.
Instructions
Get how search frequency changes over time for a keyword (daily, weekly, or monthly).
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| phrase | Yes | Keyword/phrase to analyze in Wordstat. | |
| period | No | Aggregation period. Default is PERIOD_WEEKLY. | |
| fromDate | No | Start datetime in ISO-8601 format. If omitted, a safe default is used. | |
| toDate | No | End datetime in ISO-8601 format. If omitted, a safe default is used. | |
| regions | No | Optional list of region IDs to filter statistics. | |
| devices | No | Optional device filter: all/desktop/phone/tablet. |
Implementation Reference
- src/register-tools.ts:259-317 (registration)Registration of the 'wordstat_get_dynamics' tool with input schema and handler function.
server.registerTool( "wordstat_get_dynamics", { description: "Get how search frequency changes over time for a keyword (daily, weekly, or monthly).", inputSchema: { phrase: z.string().min(1).max(400).describe("Keyword/phrase to analyze in Wordstat."), period: WordstatPeriodSchema.optional().describe( "Aggregation period. Default is PERIOD_WEEKLY.", ), fromDate: z .string() .optional() .describe("Start datetime in ISO-8601 format. If omitted, a safe default is used."), toDate: z .string() .optional() .describe("End datetime in ISO-8601 format. If omitted, a safe default is used."), regions: z .array(z.string().min(1)) .max(100) .optional() .describe("Optional list of region IDs to filter statistics."), devices: z .array(WordstatDeviceSchema) .max(3) .optional() .describe("Optional device filter: all/desktop/phone/tablet."), }, }, async ({ phrase, period, fromDate, toDate, regions, devices }) => { return withToolErrorHandling(async () => { const selectedPeriod = period ?? "PERIOD_WEEKLY"; const defaultRange = getDefaultDynamicsRange(selectedPeriod); const response = await client.post<Record<string, unknown>>("/v2/wordstat/dynamics", { phrase, period: selectedPeriod, fromDate: fromDate ?? defaultRange.fromDate, toDate: toDate ?? defaultRange.toDate, ...(regions !== undefined ? { regions } : {}), ...(devices !== undefined ? { devices } : {}), }); const structuredContent = { results: response.results, }; return { content: [ { type: "text", text: JSON.stringify(structuredContent, null, 2), }, ], structuredContent, }; }); }, ); - src/register-tools.ts:289-316 (handler)Handler function for wordstat_get_dynamics - posts to /v2/wordstat/dynamics API and returns results.
async ({ phrase, period, fromDate, toDate, regions, devices }) => { return withToolErrorHandling(async () => { const selectedPeriod = period ?? "PERIOD_WEEKLY"; const defaultRange = getDefaultDynamicsRange(selectedPeriod); const response = await client.post<Record<string, unknown>>("/v2/wordstat/dynamics", { phrase, period: selectedPeriod, fromDate: fromDate ?? defaultRange.fromDate, toDate: toDate ?? defaultRange.toDate, ...(regions !== undefined ? { regions } : {}), ...(devices !== undefined ? { devices } : {}), }); const structuredContent = { results: response.results, }; return { content: [ { type: "text", text: JSON.stringify(structuredContent, null, 2), }, ], structuredContent, }; }); }, - src/register-tools.ts:264-287 (schema)Input schema for wordstat_get_dynamics: phrase (string), period (WordstatPeriodSchema), fromDate, toDate (ISO-8601 strings), regions (array of strings), devices (array of WordstatDeviceSchema).
inputSchema: { phrase: z.string().min(1).max(400).describe("Keyword/phrase to analyze in Wordstat."), period: WordstatPeriodSchema.optional().describe( "Aggregation period. Default is PERIOD_WEEKLY.", ), fromDate: z .string() .optional() .describe("Start datetime in ISO-8601 format. If omitted, a safe default is used."), toDate: z .string() .optional() .describe("End datetime in ISO-8601 format. If omitted, a safe default is used."), regions: z .array(z.string().min(1)) .max(100) .optional() .describe("Optional list of region IDs to filter statistics."), devices: z .array(WordstatDeviceSchema) .max(3) .optional() .describe("Optional device filter: all/desktop/phone/tablet."), }, - src/register-tools.ts:96-125 (helper)getDefaultDynamicsRange helper function that calculates default fromDate/toDate based on the period (weekly/monthly/daily).
function getDefaultDynamicsRange(period: "PERIOD_MONTHLY" | "PERIOD_WEEKLY" | "PERIOD_DAILY"): { fromDate: string; toDate: string; } { let toDate = new Date(); const fromDate = new Date(toDate); if (period === "PERIOD_WEEKLY") { const day = toDate.getUTCDay(); const deltaToPreviousSunday = day === 0 ? 7 : day; toDate.setUTCDate(toDate.getUTCDate() - deltaToPreviousSunday); toDate.setUTCHours(23, 59, 59, 0); fromDate.setTime(toDate.getTime()); fromDate.setUTCDate(fromDate.getUTCDate() - 27); fromDate.setUTCHours(0, 0, 0, 0); } else if (period === "PERIOD_MONTHLY") { fromDate.setUTCMonth(fromDate.getUTCMonth() - 6); fromDate.setUTCDate(1); fromDate.setUTCHours(0, 0, 0, 0); } else { const dailyRange = getIsoDateRange(30); return dailyRange; } return { fromDate: fromDate.toISOString(), toDate: toDate.toISOString(), }; } - src/register-tools.ts:54-54 (schema)WordstatPeriodSchema: zod enum defining the allowed period values PERIOD_MONTHLY, PERIOD_WEEKLY, PERIOD_DAILY.
const WordstatPeriodSchema = z.enum(["PERIOD_MONTHLY", "PERIOD_WEEKLY", "PERIOD_DAILY"]);