How OpenSEO's AI Visibility Tracking Utilizes the AiOptimizationApi: 5 Core Workflows
OpenSEO leverages the AiOptimizationApi through a centralized, type-safe client architecture that wraps DataForSEO's LLM mention endpoints to track brand visibility across AI models like ChatGPT, Claude, and Gemini.
OpenSEO (every-app/open-seo) is an open-source SEO platform that integrates DataForSEO's AiOptimizationApi to monitor how brands appear in large language model (LLM) generated responses. This article examines the server-side implementation of AI visibility tracking, detailing the typed helper functions, validation schemas, and error handling mechanisms that transform raw API responses into actionable analytics.
Architecture of the AiOptimizationApi Integration
The AI visibility system consists of a thin, well-typed abstraction layer over DataForSEO's endpoints, split between core client configuration and specialized fetch utilities.
The Core Client Configuration (src/server/lib/dataforseo/core.ts)
The foundation of AI visibility tracking resides in src/server/lib/dataforseo/core.ts, where the aiOptimizationApi instance is created. This pre-configured client targets DataForSEO's /v3/ai_optimization/* service path and automatically injects the classifyAiSearchError utility via createDataforseoBillingClassifier. This integration ensures that billing-related errors—such as quota exhaustion or balance issues—are intercepted and classified before reaching the UI layer.
The Typed Wrapper Layer (src/server/lib/dataforseo/ai.ts)
Building atop the core client, src/server/lib/dataforseo/ai.ts exposes five specialized functions that map directly to DataForSEO endpoints. Each function provides strongly-typed request parameters and return values, abstracting the underlying HTTP complexity while exposing LLM-specific metrics to the frontend components defined in src/web/src/lib/feature-pages.ts.
5 Core AI Visibility Tracking Workflows
The AiOptimizationApi supports distinct visibility operations, each encapsulated by a dedicated server function.
1. Discovering Brand Mentions with fetchLlmMentionsSearch
To locate where a brand or keyword appears in AI-generated answers, the fetchLlmMentionsSearch function issues POST requests to the llm_mentions/search/live endpoint. This workflow supports targeting by domain or specific keywords, filtered by platform (e.g., "chat_gpt"), geographic location codes, and language.
import { fetchLlmMentionsSearch } from "@/server/lib/dataforseo/ai";
const mentions = await fetchLlmMentionsSearch({
target: { domain: "example.com" }, // or { keyword: "target keyword" }
platform: "chat_gpt",
locationCode: 2840, // United States
languageCode: "en",
limit: 200,
});
console.log(mentions.data); // Array<LlmMentionItem>
2. Retrieving Aggregated Visibility Metrics
The fetchLlmAggregatedMetrics function queries the llm_mentions/aggregated_metrics/live endpoint to retrieve high-level KPIs, including total mention counts and composite visibility scores. This enables trend analysis without processing individual mention records.
import { fetchLlmAggregatedMetrics } from "@/server/lib/dataforseo/ai";
const metrics = await fetchLlmAggregatedMetrics({
target: { domain: "example.com" },
platform: "chat_gpt",
locationCode: 2840,
languageCode: "en",
});
console.log(metrics.data); // LlmAggregatedTotal (mentions, visibility scores, etc.)
3. Identifying Top-Cited Pages with fetchLlmTopPages
For content optimization, the fetchLlmTopPages function calls llm_mentions/top_pages/live to surface which specific URLs receive the most citations from AI models. This data helps identify which content assets drive AI visibility.
import { fetchLlmTopPages } from "@/server/lib/dataforseo/ai";
const topPages = await fetchLlmTopPages({
target: { domain: "example.com" },
platform: "chat_gpt",
locationCode: 2840,
languageCode: "en",
});
console.log(topPages.data); // Array<LlmTopPagesItem>
4. Cross-Target Competitive Benchmarking
fetchLlmCrossAggregatedMetrics enables comparative analysis by querying the llm_mentions/cross_aggregated_metrics/live endpoint. This accepts multiple target groups in a single request, returning side-by-side visibility metrics for benchmarking a brand against competitors.
import { fetchLlmCrossAggregatedMetrics } from "@/server/lib/dataforseo/ai";
const cross = await fetchLlmCrossAggregatedMetrics({
groups: [
{ key: "Our Brand", target: { domain: "example.com" } },
{ key: "Rival A", target: { domain: "rival-a.com" } },
{ key: "Rival B", target: { domain: "rival-b.com" } },
],
platform: "chat_gpt",
locationCode: 2840,
languageCode: "en",
});
console.log(cross.data); // Array<LlmCrossAggregatedItem>
5. Capturing Model-Specific LLM Responses
Unlike aggregation endpoints, fetchLlmResponse retrieves actual LLM output by selecting the appropriate sub-endpoint—chat_gpt, claude, gemini, or perplexity—based on the modelSlug parameter. The function validates the model name against ACCEPTED_LLM_MODEL_NAMES before dispatching to ensure API compatibility.
import { fetchLlmResponse } from "@/server/lib/dataforseo/ai";
const answer = await fetchLlmResponse({
userPrompt: "What is the future of SEO?",
modelSlug: "chat_gpt",
modelName: "gpt-5",
webSearch: true,
maxOutputTokens: 1500,
webSearchCountryCode: "US",
});
console.log(answer.data); // LlmResponseResult (answer text, citations, etc.)
Type Safety with Zod Schema Validation
All API responses undergo strict runtime validation via Zod schemas defined in src/server/lib/dataforseoLlmSchemas.ts. Key schemas include:
- llmMentionItemSchema – Validates individual mention records
- llmAggregatedTotalSchema – Validates aggregated metric totals
- llmTopPagesItemSchema – Validates top-page citation data
This validation layer ensures that only correctly-typed data reaches the client, preventing runtime errors from API schema changes and maintaining type safety across the AI visibility tracking pipeline.
Billing Protection and Error Handling
The aiOptimizationApi client integrates createDataforseoBillingClassifier to automatically classify errors returned by DataForSEO. When quota limits are reached or account balances are insufficient, classifyAiSearchError categorizes these specifically as billing errors rather than technical failures. This allows the UI to display contextual messages about account limits instead of generic error alerts, maintaining transparency in operational costs.
Summary
- Centralized Client:
aiOptimizationApiinsrc/server/lib/dataforseo/core.tscreates a dedicated, pre-configured connection to DataForSEO's/v3/ai_optimization/endpoints. - Five Core Operations: The wrapper functions in
src/server/lib/dataforseo/ai.tshandle mentions search, metric aggregation, top-page analysis, competitive benchmarking, and model-specific response retrieval. - Strict Validation: Zod schemas in
src/server/lib/dataforseoLlmSchemas.tsenforce type safety for all LLM data structures. - Billing Awareness: Automatic error classification prevents API quota issues from disrupting the user experience with cryptic technical messages.
- Extensible Design: New AI models can be supported by updating the
ACCEPTED_LLM_MODEL_NAMESmap and extending the request classes in the underlying dataforseo-client.
Frequently Asked Questions
What specific DataForSEO endpoints does OpenSEO use for AI visibility tracking?
OpenSEO utilizes DataForSEO's AiOptimizationApi endpoints under the /v3/ai_optimization/ path, specifically llm_mentions/search/live, llm_mentions/aggregated_metrics/live, llm_mentions/top_pages/live, llm_mentions/cross_aggregated_metrics/live, and model-specific endpoints including chat_gpt, claude, gemini, and perplexity.
How does OpenSEO ensure type safety when processing LLM API responses?
The codebase employs Zod schemas located in src/server/lib/dataforseoLlmSchemas.ts to validate every response from the AiOptimizationApi. Schemas such as llmMentionItemSchema and llmAggregatedTotalSchema guarantee that only correctly-typed data reaches the frontend, preventing runtime errors from schema drift.
Can OpenSEO track AI visibility across different models like Claude and Perplexity?
Yes. The fetchLlmResponse function supports multiple models by selecting the appropriate endpoint based on the modelSlug parameter, with validation against the ACCEPTED_LLM_MODEL_NAMES constant. For aggregation features, the platform parameter accepts values including "chat_gpt", "claude", "gemini", and "perplexity".
How does the system handle API billing errors or quota exhaustion?
The aiOptimizationApi client automatically injects classifyAiSearchError via createDataforseoBillingClassifier from src/server/lib/dataforseo/core.ts. This utility intercepts billing-related errors—such as insufficient balance or quota limits—allowing the application to distinguish between account issues and technical failures for appropriate user notification.
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 →