Skip to main content
Glama
pagespeed.ts3.99 kB
/** * Google PageSpeed Insights Performance Analyzer * API v5: https://pagespeedonline.googleapis.com/pagespeedonline/v5/runPagespeed * Quota: 25,000 requests/day with free API key */ export interface PageSpeedOptions { /** Strategy: mobile or desktop (default: mobile) */ strategy?: 'mobile' | 'desktop'; /** Optional API key (recommended for production, 25K/day quota) */ apiKey?: string; /** Categories to test (default: all) */ categories?: Array<'performance' | 'accessibility' | 'best-practices' | 'seo'>; } export interface PageSpeedMetrics { firstContentfulPaint?: number; largestContentfulPaint?: number; totalBlockingTime?: number; cumulativeLayoutShift?: number; speedIndex?: number; timeToInteractive?: number; } export interface PageSpeedResponse { lighthouseResult: { categories: { performance?: { score: number }; accessibility?: { score: number }; 'best-practices'?: { score: number }; seo?: { score: number }; }; audits: Record<string, any>; }; loadingExperience?: { metrics: Record<string, any>; }; } export interface PageSpeedResult { tool: 'pagespeed'; success: boolean; url: string; strategy: string; performance_score?: number; accessibility_score?: number; best_practices_score?: number; seo_score?: number; metrics?: PageSpeedMetrics; crux_data?: boolean; error?: string; raw?: PageSpeedResponse; } /** * Analyze website performance using Google PageSpeed Insights */ export async function analyzePageSpeed( url: string, options: PageSpeedOptions = {} ): Promise<PageSpeedResult> { try { const strategy = options.strategy || 'mobile'; const categories = options.categories || ['performance', 'accessibility', 'best-practices', 'seo']; // Build API URL const params = new URLSearchParams({ url, strategy, }); // Add categories categories.forEach(cat => params.append('category', cat)); // Add API key if provided if (options.apiKey) { params.set('key', options.apiKey); } const apiUrl = `https://pagespeedonline.googleapis.com/pagespeedonline/v5/runPagespeed?${params.toString()}`; const response = await fetch(apiUrl); if (!response.ok) { throw new Error(`PageSpeed API error: ${response.status} ${response.statusText}`); } const data: PageSpeedResponse = await response.json(); // Extract scores (0-1 range, convert to 0-100) const scores = data.lighthouseResult.categories; const performance_score = scores.performance ? Math.round(scores.performance.score * 100) : undefined; const accessibility_score = scores.accessibility ? Math.round(scores.accessibility.score * 100) : undefined; const best_practices_score = scores['best-practices'] ? Math.round(scores['best-practices'].score * 100) : undefined; const seo_score = scores.seo ? Math.round(scores.seo.score * 100) : undefined; // Extract key metrics (convert to milliseconds) const audits = data.lighthouseResult.audits; const metrics: PageSpeedMetrics = { firstContentfulPaint: audits['first-contentful-paint']?.numericValue, largestContentfulPaint: audits['largest-contentful-paint']?.numericValue, totalBlockingTime: audits['total-blocking-time']?.numericValue, cumulativeLayoutShift: audits['cumulative-layout-shift']?.numericValue, speedIndex: audits['speed-index']?.numericValue, timeToInteractive: audits['interactive']?.numericValue, }; return { tool: 'pagespeed', success: true, url, strategy, performance_score, accessibility_score, best_practices_score, seo_score, metrics, crux_data: !!data.loadingExperience, raw: data, }; } catch (error) { return { tool: 'pagespeed', success: false, url, strategy: options.strategy || 'mobile', error: error instanceof Error ? error.message : String(error), }; } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/cordlesssteve/webby-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server