Routing Logic for the Google Ads Keyword-Data Provider in googleAdsOnly Countries

The Google Ads keyword-data provider in the every-app/open-seo repository routes requests through a dedicated API endpoint that validates ISO country codes against a strict whitelist before invoking the Google Ads API, rejecting unsupported regions with a 400 Bad Request response.

The every-app/open-seo project implements a secure, country-restricted routing layer for its Google Ads keyword research functionality. This routing logic ensures that keyword data queries are processed only for predefined geographic markets, preventing unauthorized access to unsupported regions while maintaining clean separation between route handling and external API integration.

API Endpoint and Route Structure

The keyword-data service exposes a dedicated route that handles country-specific filtering through query parameters.

Route Registration

The server-side routing tree is auto-generated in web/src/routeTree.gen.ts. This file registers the marketing section route that maps HTTP requests to the concrete handler:

{
  id: '/marketing/google-ads/keyword-data',
  path: '/marketing/google-ads/keyword-data',
  //…other route metadata
}

Incoming GET requests to /api/google-ads/keyword-data are matched against this entry and forwarded to web/src/routes/_marketing/google-ads/keyword-data.ts.

Request Handling

The handler expects a countries query parameter containing comma-separated ISO-3166-1 alpha-2 codes. The router extracts these values and initiates the validation pipeline before any external API calls occur.

Country Validation Workflow

The routing logic enforces geographic restrictions through a whitelist check defined in src/lib/googleAds/countries.ts.

The SUPPORTED_COUNTRIES Set contains the allowed region codes:

const SUPPORTED_COUNTRIES = new Set([
  'US', 'CA', 'GB', 'AU', 'DE', 'FR', 'JP', 'BR', // …etc.
]);

Inside the route handler, the validation logic parses and verifies the input:

const url = new URL(request.url);
const raw = url.searchParams.get('countries') ?? '';
const countries = raw.split(',').map(c => c.trim().toUpperCase());

if (!countries.length || !countries.every(c => SUPPORTED_COUNTRIES.has(c))) {
  return new Response('Invalid or unsupported country codes', { status: 400 });
}

Any request containing country codes outside this whitelist immediately receives a 400 Bad Request response, preventing unauthorized or accidental queries for unsupported regions.

Provider Invocation

After successful validation, the handler instantiates the GoogleAdsKeywordDataProvider class from src/lib/googleAds/KeywordDataProvider.ts and invokes its getKeywords method:

const provider = new GoogleAdsKeywordDataProvider();
const result = await provider.getKeywords({ countries });

The provider constructs a Google Ads API request that includes a LocationSearchParameter for every validated country code, ensuring keyword suggestions, search volume estimates, and competition metrics reflect only the specified geographic markets.

The final response returns the provider's JSON payload with a 200 OK status:

return new Response(JSON.stringify(result), {
  headers: { 'Content-Type': 'application/json' },
  status: 200,
});

Client Integration Example

Applications consume this endpoint by passing the required country parameter:

fetch(
  '/api/google-ads/keyword-data?countries=US,CA,GB',
  { method: 'GET' }
)
  .then(r => r.ok ? r.json() : Promise.reject(r.status))
  .then(data => console.log('Keyword data:', data))
  .catch(err => console.error('Request failed:', err));

Summary

  • The /api/google-ads/keyword-data route accepts GET requests with a mandatory countries query parameter containing comma-separated ISO-3166-1 alpha-2 codes.
  • The handler in web/src/routes/_marketing/google-ads/keyword-data.ts validates all country codes against the SUPPORTED_COUNTRIES whitelist defined in src/lib/googleAds/countries.ts.
  • Requests containing unsupported codes receive an immediate 400 Bad Request without invoking the external API.
  • Valid requests instantiate GoogleAdsKeywordDataProvider and call getKeywords(), which builds location-specific API calls using LocationSearchParameter instances.
  • This whitelist approach ensures keyword data is only retrieved for explicitly permitted regions, controlling API costs and ensuring data compliance.

Frequently Asked Questions

What happens if I request keyword data for an unsupported country?

The route handler checks every submitted country code against the SUPPORTED_COUNTRIES Set in src/lib/googleAds/countries.ts. If any code is missing from the whitelist, the handler returns a 400 Bad Request response with the message "Invalid or unsupported country codes" and never calls the Google Ads API.

Where is the country whitelist defined in the codebase?

The whitelist is exported from src/lib/googleAds/countries.ts as a constant Set named SUPPORTED_COUNTRIES. This file contains the complete list of ISO-3166-1 alpha-2 codes that the keyword-data provider is authorized to query.

How does the provider handle multiple countries in a single request?

The GoogleAdsKeywordDataProvider class accepts an array of country codes and constructs a Google Ads API request that includes a separate LocationSearchParameter for each country. This generates keyword ideas and metrics aggregated across all specified locations while maintaining the restriction to whitelisted regions only.

Is the route path configurable or auto-generated?

The route path is defined in the auto-generated file web/src/routeTree.gen.ts, which maps /marketing/google-ads/keyword-data to the handler at web/src/routes/_marketing/google-ads/keyword-data.ts. While the underlying framework supports route configuration, the actual path structure follows the file-based routing convention used throughout the project.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →