How Target Detection Identifies Tracked Domains in Google Search Console Data
Open SEO uses the detectTarget utility in src/shared/targetDetection.ts to distinguish domains from keywords by validating that input strings contain no spaces, include at least one period, and successfully pass domain normalization, ensuring only configured tracked domains are queried against Google Search Console properties.
The every-app/open-seo repository implements a strict validation layer to prevent accidental keyword queries against Google Search Console (GSC) APIs. Understanding how target detection identifies tracked domains within Google Search Console data is essential for developers integrating these Model Context Protocol (MCP) tools, as it ensures all requests are scoped exclusively to verified domain properties.
The Four-Step Detection Heuristic
The detectTarget function implements a deterministic classification pipeline that processes raw user input before constructing any GSC API request payload.
Input Sanitization
First, the utility trims surrounding whitespace from the raw input string. This eliminates accidental formatting characters or copy-paste artifacts that could interfere with subsequent validation logic.
Domain Pattern Validation
The function validates domain-like structure by enforcing two strict criteria: the string must contain no spaces, and it must include at least one period (.). This heuristic filters out obvious keyword phrases while allowing potential domain candidates to proceed to normalization.
Normalization and Final Classification
The candidate string is passed to normalizeDomain, imported from the schema definitions in src/types/schemas/domain.ts. If normalization succeeds and yields a hostname that still contains a period, the input is classified as a domain. Should normalization throw an exception, return an invalid format, or if the initial pattern checks fail, the classification falls back to keyword.
Integration with GSC MCP Tools
When users invoke Google Search Console tools—such as the "Get Google Search Console performance" or "Inspect URLs" functions—the raw target parameter undergoes this detection process immediately. If detectTarget resolves to a domain type, the tool constructs the request payload using the normalized domain as the siteUrl, ensuring queries execute only against the connected property's root domain and preventing arbitrary keyword searches.
import { detectTarget } from "@/shared/targetDetection";
const input1 = "example.com";
const input2 = "Best coffee shops";
console.log(detectTarget(input1)); // → { type: "domain", value: "example.com" }
console.log(detectTarget(input2)); // → { type: "keyword", value: "Best coffee shops" }
The following implementation demonstrates how GSC services consume this detection to enforce domain-only queries:
import { detectTarget } from "@/shared/targetDetection";
import { GscService } from "@/server/features/gsc/services/GscService";
export async function fetchPerformance(rawTarget: string, args: PerfArgs) {
const { type, value } = detectTarget(rawTarget);
// GSC only works with a domain (the connected property)
if (type !== "domain") {
throw new Error("Target must be a domain for GSC queries");
}
// Build the request – the `value` is the normalized domain
const result = await GscService.getPerformance({
...args,
// `siteUrl` is derived from the domain
siteUrl: value,
});
return result;
}
Key Source Files
The detection logic spans three critical locations in the codebase:
src/shared/targetDetection.ts(lines 13-30): Implements thedetectTargetheuristic that decides between a domain and a keyword classification.src/server/mcp/tools/search-console-tools.ts(lines 20-30): Defines the GSC MCP tools that rely on the detected target to query the connected Search Console property.src/types/schemas/domain.ts: Provides thenormalizeDomainroutine used bydetectTargetto validate and canonicalize domain strings according to project schemas.
Summary
- Input validation occurs through
detectTargetinsrc/shared/targetDetection.ts, which requires strings to contain periods and passnormalizeDomainvalidation to qualify as domains. - Classification logic rejects any input containing spaces or failing normalization, categorizing these as keywords rather than trackable domains.
- GSC tool integration enforces strict domain-only queries by checking the
typeproperty before constructing API requests, preventing accidental queries on arbitrary keywords. - Architecture consistency is maintained through shared schema definitions that ensure uniform domain canonicalization across the entire Open SEO codebase.
Frequently Asked Questions
What happens if I pass a keyword instead of a domain to a GSC tool?
The tool will throw an error indicating that the target must be a domain. The detectTarget function classifies space-containing strings or failed normalizations as keywords, and the GSC service explicitly checks for type === "domain" before executing queries against Google Search Console data.
Does the detection support subdomains or only root domains?
The heuristic supports any valid hostname that passes normalizeDomain, including subdomains like blog.example.com. As long as the string contains no spaces, includes a period, and successfully normalizes, it is accepted as a domain target for tracked properties.
Where is the domain normalization logic defined?
The normalization routine is implemented in src/types/schemas/domain.ts and imported by the target detection module. This centralized definition ensures consistent canonicalization across all Google Search Console integrations in the Open SEO project.
Can the detection logic be bypassed for advanced use cases?
No, the detectTarget validation is mandatory for all GSC MCP tools defined in src/server/mcp/tools/search-console-tools.ts. This enforcement ensures that only configured, tracked domains within the Google Search Console property are queried, maintaining data integrity and API compliance.
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 →