OpenSEO Language Resolution: How Keyword Data Differs from SERP Data
OpenSEO resolves languages differently for keyword data (tied to location markets) versus SERP data (standalone selection from a fixed list), enforcing strict location dependency for keywords while allowing flexible language-location combinations for SERP requests.
The every-app/open-seo repository handles search data retrieval through two distinct pipelines: keyword research APIs (Labs and Google Ads) and SERP tracking APIs. Understanding the language resolution differences between these systems is critical for correctly configuring API requests and interpreting localization results.
Keyword Data Language Resolution
Keyword data operations in OpenSEO enforce a location-dependent language model where the selected language must align with the target market's primary search corpus.
Market-Based Default Selection
When processing keyword data requests, the system derives the default language from the location's primary search market. According to comments in src/shared/keyword-locations.ts, the implementation selects the language with the largest keyword corpus for the specified country when no explicit language code is provided.
// src/shared/keyword-locations.ts#L13
// Logic selects the language with the biggest keyword corpus as the default
const language = languageCode ?? getDefaultLanguageForLocation(locationCode);
The getDefaultLanguageForLocation function maps country codes to their dominant search languages based on DataForSEO's keyword database coverage, ensuring that keyword volume and competition metrics reflect the most relevant linguistic market for that geography.
Strict Validation Requirements
Unlike SERP operations, keyword data endpoints require both location and language parameters to form a valid pair. The projectLanguageCodeField schema explicitly rejects language-only requests:
// Validation logic at src/shared/keyword-locations.ts#L824-L826
if (!locationCode && languageCode) {
throw new Error('A language requires a location.');
}
This validation ensures that keyword metrics (search volume, CPC, competition) reflect actual market conditions where specific language-location pairs are supported by the underlying data provider.
SERP Data Language Resolution
SERP data handling follows a standalone language selection model that decouples language choice from location constraints, offering broader flexibility for rank tracking scenarios.
Independent Language Options
Rather than deriving languages from location markets, SERP resolution uses the SERP_LANGUAGE_OPTIONS constant defined at line 549 of src/shared/keyword-locations.ts. This array enumerates every language code accepted by the DataForSEO SERP endpoint, independent of geographic restrictions:
// src/shared/keyword-locations.ts#L549
export const SERP_LANGUAGE_OPTIONS = [
{ code: 'en', name: 'English' },
{ code: 'es', name: 'Spanish' },
{ code: 'fr', name: 'French' },
// ... additional supported languages
] as const;
The SERP implementation in src/server/lib/dataforseo/serp.ts references these options directly, allowing any supported language code to accompany any location code in the request payload.
Default Fallback Behavior
When SERP requests omit the language parameter, the system defaults to English (en) rather than attempting to resolve a location-appropriate language. This behavior contrasts sharply with keyword data resolution, which actively queries the location-to-language mapping:
// SERP language resolution defaults to English
const resolveSerpLanguage = (requestedCode?: string) => {
const available = SERP_LANGUAGE_OPTIONS.map(l => l.code);
return requestedCode && available.includes(requestedCode)
? requestedCode
: 'en';
};
Key Implementation Differences
The architectural distinction between these resolution strategies manifests in three critical areas:
| Resolution Aspect | Keyword Data | SERP Data |
|---|---|---|
| Source Authority | Location's primary market corpus (getDefaultLanguageForLocation) |
Fixed array (SERP_LANGUAGE_OPTIONS) |
| Location Dependency | Required—language invalid without location | Optional—any language works with any location |
| Default Value | Location's dominant language (largest keyword volume) | Hardcoded English (en) |
| Schema Validation | src/types/schemas/keywords.ts enforces location presence |
src/types/schemas/rank-tracking.ts validates against SERP list |
Practical Implementation Examples
When building requests for the OpenSEO system, implement resolution logic that respects these distinct pathways:
import {
getDefaultLanguageForLocation,
SERP_LANGUAGE_OPTIONS
} from '@/shared/keyword-locations';
// --- Keyword Data Resolution ---
function resolveKeywordLanguage(locationCode?: number, languageCode?: string) {
// Enforces location requirement
if (languageCode && !locationCode) {
throw new Error('A language requires a location.');
}
// Derives from market corpus if omitted
const resolvedLanguage = languageCode ??
getDefaultLanguageForLocation(locationCode!);
return { locationCode, languageCode: resolvedLanguage };
}
// --- SERP Data Resolution ---
function resolveSerpLanguage(locationCode: number, languageCode?: string) {
const validCodes = SERP_LANGUAGE_OPTIONS.map(l => l.code);
// Falls back to English, no location lookup
const resolvedLanguage = languageCode && validCodes.includes(languageCode)
? languageCode
: 'en';
return { locationCode, languageCode: resolvedLanguage };
}
The keyword resolution function relies on market data validation rules defined in src/shared/keyword-locations.ts, while the SERP function simply checks membership in the supported languages array.
Summary
- Keyword data requires location-dependent language resolution where the default derives from the location's largest keyword corpus, and validation enforces that languages cannot exist without accompanying locations.
- SERP data uses a standalone language list (
SERP_LANGUAGE_OPTIONS) that permits any supported language with any location, defaulting to English when unspecified. - Validation schemas differ between
src/types/schemas/keywords.ts(location-required) andsrc/types/schemas/rank-tracking.ts(flexible language selection). - Implementation files centralize this logic in
src/shared/keyword-locations.ts, with line 13 handling keyword defaults and line 549 defining SERP options.
Frequently Asked Questions
Can I use any language with any location in OpenSEO SERP requests?
Yes. The SERP pipeline accepts any language code from SERP_LANGUAGE_OPTIONS regardless of the specified location. This differs from keyword data, where language choices are constrained by the location's available keyword markets. The system performs no validation that the language is "appropriate" for the geographic region.
Why does OpenSEO require a location when specifying a language for keyword data?
Data accuracy requirements. Keyword metrics (search volume, competition, CPC) vary significantly by market, and DataForSEO's keyword database organizes data by location-language pairs. The validation at lines 824-826 of src/shared/keyword-locations.ts prevents requests for unsupported combinations that would return invalid or empty datasets.
What happens if I omit the language code in a keyword data request?
The system selects the location's dominant language. Using the getDefaultLanguageForLocation function, OpenSEO chooses the language with the largest keyword corpus for that country. For example, a request for United States without a language specification defaults to English, while a request for Canada might default to English based on corpus size, though both English and French markets exist.
Where are the valid SERP language codes defined?
In src/shared/keyword-locations.ts at line 549. The SERP_LANGUAGE_OPTIONS constant array contains the complete list of language codes accepted by the DataForSEO SERP API. This list is imported and referenced by src/server/lib/dataforseo/serp.ts when constructing API requests and by validation schemas to ensure request integrity.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →