Get Page Titles
rybbit_get_page_titlesRetrieve the most-viewed page titles for a site, showing pageviews and unique sessions per title. Provides readable names instead of raw paths.
Instructions
Get the most-viewed page titles for a site, broken down by pageviews and unique sessions. Complements rybbit_get_metric with parameter='pathname' by giving the human-readable page title instead of just the path.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| siteId | Yes | Site ID (numeric ID or domain identifier) | |
| startDate | No | Start date in ISO format (YYYY-MM-DD) | |
| endDate | No | End date in ISO format (YYYY-MM-DD) | |
| timeZone | No | IANA timezone (e.g., Europe/Prague). Default: UTC | |
| filters | No | Array of filters. Example: [{parameter:'browser',type:'equals',value:['Chrome']},{parameter:'country',type:'equals',value:['US','DE']}] | |
| pastMinutesStart | No | Alternative to dates: minutes ago start (e.g., 60 = last hour) | |
| pastMinutesEnd | No | Alternative to dates: minutes ago end (default 0 = now) |
Implementation Reference
- src/tools/config.ts:450-490 (registration)Registers the 'rybbit_get_page_titles' tool with the MCP server, including its title, description, input schema (analyticsInputSchema), annotations, and the handler callback.
server.registerTool( "rybbit_get_page_titles", { title: "Get Page Titles", description: "Get the most-viewed page titles for a site, broken down by pageviews and unique sessions. Complements rybbit_get_metric with parameter='pathname' by giving the human-readable page title instead of just the path.", inputSchema: { ...analyticsInputSchema, }, annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true, }, }, async (args) => { try { const { siteId, ...rest } = args as { siteId: string; startDate?: string; endDate?: string; timeZone?: string; filters?: Array<{ parameter: string; type: string; value: (string | number)[] }>; pastMinutesStart?: number; pastMinutesEnd?: number; }; const params = client.buildAnalyticsParams(rest); const data = await client.get(`/sites/${siteId}/page-titles`, params); return { content: [{ type: "text" as const, text: truncateResponse(data) }], }; } catch (err) { const message = err instanceof Error ? err.message : String(err); return { content: [{ type: "text" as const, text: `Error: ${message}` }], isError: true, }; } } ); - src/tools/config.ts:466-490 (handler)Handler function for rybbit_get_page_titles. Extracts siteId and analytics params, calls client.get('/sites/{siteId}/page-titles', params), and returns the response or an error.
async (args) => { try { const { siteId, ...rest } = args as { siteId: string; startDate?: string; endDate?: string; timeZone?: string; filters?: Array<{ parameter: string; type: string; value: (string | number)[] }>; pastMinutesStart?: number; pastMinutesEnd?: number; }; const params = client.buildAnalyticsParams(rest); const data = await client.get(`/sites/${siteId}/page-titles`, params); return { content: [{ type: "text" as const, text: truncateResponse(data) }], }; } catch (err) { const message = err instanceof Error ? err.message : String(err); return { content: [{ type: "text" as const, text: `Error: ${message}` }], isError: true, }; } } ); - src/schemas.ts:85-111 (schema)analyticsInputSchema used as the input schema for rybbit_get_page_titles. Defines siteId, startDate, endDate, timeZone, filters, pastMinutesStart, pastMinutesEnd.
export const analyticsInputSchema = { siteId: siteIdSchema, startDate: z .string() .optional() .describe("Start date in ISO format (YYYY-MM-DD)"), endDate: z .string() .optional() .describe("End date in ISO format (YYYY-MM-DD)"), timeZone: z .string() .optional() .describe("IANA timezone (e.g., Europe/Prague). Default: UTC"), filters: z .array(filterSchema) .optional() .describe("Array of filters. Example: [{parameter:'browser',type:'equals',value:['Chrome']},{parameter:'country',type:'equals',value:['US','DE']}]"), pastMinutesStart: z .number() .optional() .describe("Alternative to dates: minutes ago start (e.g., 60 = last hour)"), pastMinutesEnd: z .number() .optional() .describe("Alternative to dates: minutes ago end (default 0 = now)"), }; - src/client.ts:114-144 (helper)buildAnalyticsParams helper method on RybbitClient, converts the analytics options to URL query parameters (snake_case) used in the API call.
buildAnalyticsParams(options: { startDate?: string; endDate?: string; timeZone?: string; filters?: FilterParam[]; pastMinutesStart?: number; pastMinutesEnd?: number; bucket?: string; page?: number; limit?: number; offset?: number; }): QueryParams { const params: QueryParams = {}; if (options.startDate) params.start_date = options.startDate; if (options.endDate) params.end_date = options.endDate; if (options.timeZone) params.time_zone = options.timeZone; if (options.filters && options.filters.length > 0) { params.filters = JSON.stringify(options.filters); } if (options.pastMinutesStart !== undefined) params.past_minutes_start = options.pastMinutesStart; if (options.pastMinutesEnd !== undefined) params.past_minutes_end = options.pastMinutesEnd; if (options.bucket) params.bucket = options.bucket; if (options.page !== undefined) params.page = options.page; if (options.limit !== undefined) params.limit = options.limit; if (options.offset !== undefined) params.offset = options.offset; return params; } - src/client.ts:164-181 (helper)truncateResponse helper function that truncates JSON responses to CHARACTER_LIMIT (25000 chars) for safe display.
export function truncateResponse(data: unknown): string { const json = JSON.stringify(data, null, 2); if (json.length <= CHARACTER_LIMIT) return json; if (Array.isArray(data)) { const half = Math.max(1, Math.floor(data.length / 2)); const truncated = data.slice(0, half); const result = { data: truncated, truncated: true, truncation_message: `Response truncated from ${data.length} to ${half} items (exceeded ${CHARACTER_LIMIT} char limit). Use pagination (page/limit) or add filters to reduce results.`, }; return JSON.stringify(result, null, 2); } return json.slice(0, CHARACTER_LIMIT) + `\n\n[Response truncated at ${CHARACTER_LIMIT} characters. Use filters or pagination to reduce data.]`; }