Skip to main content
Glama
ahonn

Google Search Console MCP Server

by ahonn

detect_quick_wins

Identify SEO opportunities by analyzing search data to find pages with high impressions but low click-through rates that can be improved for better rankings.

Instructions

Automatically detect SEO quick wins and optimization opportunities

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
siteUrlYesThe site URL as defined in Search Console. Example: sc-domain:example.com (for domain resources) or http://www.example.com/ (for site prefix resources)
startDateYesStart date in YYYY-MM-DD format
endDateYesEnd date in YYYY-MM-DD format
minImpressionsNoMinimum impressions threshold for quick wins
maxCtrNoMaximum CTR percentage for quick wins detection
positionRangeMinNoMinimum position for quick wins (default: 4)
positionRangeMaxNoMaximum position for quick wins (default: 10)
estimatedClickValueNoEstimated value per click for ROI calculation
conversionRateNoEstimated conversion rate for ROI calculation

Implementation Reference

  • Core implementation of quick wins detection: filters low-CTR queries in good positions with sufficient impressions, calculates potential clicks at 5% CTR target, and ranks by opportunity size.
    private detectQuickWins( rows: any[], thresholds: { minImpressions?: number; maxCtr?: number; positionRangeMin?: number; positionRangeMax?: number; } = {} ) { const { minImpressions = 50, maxCtr = 2.0, positionRangeMin = 4, positionRangeMax = 10 } = thresholds; return rows .filter(row => { const impressions = row.impressions || 0; const ctr = (row.ctr || 0) * 100; const position = row.position || 0; return impressions >= minImpressions && ctr <= maxCtr && position >= positionRangeMin && position <= positionRangeMax; }) .map(row => { const impressions = row.impressions || 0; const currentClicks = row.clicks || 0; const currentCtr = (row.ctr || 0) * 100; const position = row.position || 0; // Calculate potential with 5% target CTR const targetCtr = 5.0; const potentialClicks = Math.round((impressions * targetCtr) / 100); const additionalClicks = Math.max(0, potentialClicks - currentClicks); return { query: row.keys?.[0] || 'N/A', page: row.keys?.[1] || 'N/A', currentPosition: Number(position.toFixed(1)), impressions: impressions, currentClicks: currentClicks, currentCtr: Number(currentCtr.toFixed(2)), potentialClicks: potentialClicks, additionalClicks: additionalClicks, opportunity: additionalClicks > 0 ? 'High' : 'Low', optimizationNote: `Move from position ${position.toFixed(1)} to improve CTR` }; }) .sort((a, b) => b.additionalClicks - a.additionalClicks); }
  • Zod schema defining input parameters for the detect_quick_wins tool, including date range and customizable thresholds.
    export const QuickWinsDetectionSchema = GSCBaseSchema.extend({ startDate: z.string().describe('Start date in YYYY-MM-DD format'), endDate: z.string().describe('End date in YYYY-MM-DD format'), minImpressions: z.number().default(50).describe('Minimum impressions threshold for quick wins'), maxCtr: z.number().default(2.0).describe('Maximum CTR percentage for quick wins detection'), positionRangeMin: z.number().default(4).describe('Minimum position for quick wins (default: 4)'), positionRangeMax: z.number().default(10).describe('Maximum position for quick wins (default: 10)'), estimatedClickValue: z.number().default(1.0).describe('Estimated value per click for ROI calculation'), conversionRate: z.number().default(0.03).describe('Estimated conversion rate for ROI calculation'), });
  • src/index.ts:58-62 (registration)
    Registration of the detect_quick_wins tool in the ListTools response.
    { name: 'detect_quick_wins', description: 'Automatically detect SEO quick wins and optimization opportunities', inputSchema: zodToJsonSchema(QuickWinsDetectionSchema), },
  • Main tool handler in the CallToolRequest switch statement: fetches search analytics data up to 25k rows and invokes enhanced analysis with quick wins detection enabled.
    case 'detect_quick_wins': { const args = QuickWinsDetectionSchema.parse(request.params.arguments); // First get search analytics data const requestBody: any = { startDate: args.startDate, endDate: args.endDate, dimensions: ['query', 'page'], rowLimit: 25000, // Maximum for comprehensive analysis }; const searchResponse = await searchConsole.searchAnalytics(args.siteUrl, requestBody); if (!searchResponse.data.rows) { return { content: [ { type: 'text', text: JSON.stringify({ message: 'No data available for quick wins analysis' }, null, 2), }, ], }; } // Apply quick wins detection const quickWinsOptions = { enableQuickWins: true, quickWinsThresholds: { minImpressions: args.minImpressions, maxCtr: args.maxCtr, positionRangeMin: args.positionRangeMin, positionRangeMax: args.positionRangeMax, }, }; const enhancedResult = await searchConsole.enhancedSearchAnalytics( args.siteUrl, requestBody, quickWinsOptions ); return { content: [ { type: 'text', text: JSON.stringify({ quickWins: (enhancedResult.data as any).quickWins, totalOpportunities: (enhancedResult.data as any).quickWins?.length || 0, thresholds: quickWinsOptions.quickWinsThresholds, analysis: 'Quick wins detection completed' }, null, 2), }, ], }; }
  • Supporting method that applies quick wins detection (and regex filtering) to search analytics results, invoked by the main tool handler.
    async enhancedSearchAnalytics( siteUrl: string, requestBody: SearchanalyticsQueryRequest, options: { regexFilter?: string; enableQuickWins?: boolean; quickWinsThresholds?: { minImpressions?: number; maxCtr?: number; positionRangeMin?: number; positionRangeMax?: number; }; } = {} ) { // Ensure requestBody is defined if (!requestBody) { throw new Error('Request body is required'); } // Apply regex filter if provided if (options.regexFilter && requestBody.dimensions?.includes('query')) { requestBody.dimensionFilterGroups = [ ...(requestBody.dimensionFilterGroups || []), { groupType: 'and', filters: [{ dimension: 'query', operator: 'includingRegex', expression: options.regexFilter }] } ]; } // Execute enhanced search analytics const result = await this.searchAnalytics(siteUrl, requestBody); // Apply quick wins detection if enabled if (options.enableQuickWins && result.data.rows) { const quickWins = this.detectQuickWins(result.data.rows, options.quickWinsThresholds); return { ...result, data: { ...result.data, quickWins: quickWins, enhancedFeatures: { regexFilterApplied: !!options.regexFilter, quickWinsEnabled: true, rowLimit: requestBody.rowLimit || 1000 } } }; } return result; }

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/ahonn/mcp-server-gsc'

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