Shared Utilities for GSC Integration in OpenSEO: Architecture and Implementation
OpenSEO centralizes Google Search Console integration through reusable TypeScript modules located in src/shared and src/server/lib, providing consistent OAuth handling, typed API clients, and structured error management across the entire application.
The OpenSEO codebase treats Google Search Console (GSC) connectivity as a first-class integration, abstracting all authentication and API concerns into shared utilities that both server-side services and client components can consume. These shared utilities for GSC integration in OpenSEO ensure that OAuth flows, API requests, and error handling remain consistent whether you're building MCP tools, UI components, or background jobs.
Core GSC Utilities Overview
OpenSEO organizes GSC functionality into five primary utility modules that separate concerns between constants, client logic, error handling, request building, and high-level orchestration:
src/shared/gsc.ts– OAuth constants and documentation URLssrc/server/lib/gscClient.ts– Authenticated API client wrappersrc/server/lib/gscErrors.ts– Typed error classessrc/server/features/gsc/searchAnalytics.ts– Request builders and dimension constantssrc/server/features/gsc/services/GscService.ts– Service layer coordinating all utilities
OAuth Constants and Configuration (src/shared/gsc.ts)
The foundation of GSC integration starts with constants that must be accessible to both the server (for Better Auth configuration) and the client (for "Connect to GSC" buttons). The src/shared/gsc.ts file exports three critical values:
GSC_OAUTH_PROVIDER_ID– The identifier used when configuring the OAuth providerGSC_OAUTH_SCOPES– Required Google OAuth scopes for Search Console accessGSC_SELF_HOSTED_SETUP_DOCS_URL– Documentation link for self-hosted instances
These constants ensure that both authentication handlers and UI components reference identical configuration values without duplication.
API Client Wrapper (src/server/lib/gscClient.ts)
The gscClient.ts module provides a thin wrapper around the Google Search Console REST API through the createGscClient factory function. This utility handles token retrieval, request signing, and error wrapping while exposing three core endpoints:
listSites()– Retrieve verified GSC propertiesquerySearchAnalytics()– Fetch search performance datainspectUrl()– Check indexing status for specific URLs
Creating the GSC Client
When initializing the client, createGscClient accepts a user ID and optional Google account ID, retrieves an access token via getAuth().api.getAccessToken, and returns an object with methods that issue signed fetch calls to the GSC API.
import { createGscClient } from '@/server/lib/gscClient';
async function listVerifiedSites(userId: string, gscAccountId?: string) {
const client = createGscClient({ userId, gscAccountId });
const sites = await client.listSites();
console.log('Verified sites:', sites);
}
Typed Error Handling (src/server/lib/gscErrors.ts)
GSC operations can fail in distinct ways—API rate limits, expired tokens, or missing connections—and OpenSEO provides specific error classes to distinguish these scenarios. The src/server/lib/gscErrors.ts file exports:
GscApiError– Wraps non-2xx HTTP responses from the GSC APIGscTokenError– Indicates token minting or refresh failuresGscNotConnectedError– Thrown when a project lacks a stored GSC connection
Higher-level services and MCP tools catch these errors to present user-friendly messages without leaking implementation details.
Search Analytics Request Builders (src/server/features/gsc/searchAnalytics.ts)
Before querying search analytics data, MCP tool inputs must conform to the GSC API's expected shape. The src/server/features/gsc/searchAnalytics.ts module provides pure-logic helpers that handle this translation.
This utility exports constants for valid dimensions, filter operators, search types, and date ranges, plus two key functions:
resolveDateRange()– Converts relative ranges likelast_28_daysinto ISO datesbuildSearchAnalyticsRequest()– Constructs the final request object with properdimensionFilterGroupsstructure
Building Structured Requests
import { buildSearchAnalyticsRequest } from '@/server/features/gsc/searchAnalytics';
const input = {
projectId: 'proj_123',
dimensions: ['query', 'page'],
dateRange: 'last_28_days',
filters: [{ dimension: 'country', operator: 'equals', expression: 'US' }],
rowLimit: 500,
};
const request = buildSearchAnalyticsRequest(input);
// Returns GSC API-compatible object with startDate, endDate, and filter groups
High-Level Service Orchestration (src/server/features/gsc/services/GscService.ts)
The GscService class ties together the client, repository, and request builders to provide project-scoped GSC operations. Rather than manually coordinating tokens and API calls throughout the codebase, developers interact with methods like:
getPerformance()– Retrieve analytics data for a projectinspectUrls()– Batch check indexing statuslistSitesForUserWithGrantStatus()– Show available sites with connection status
GscService pulls the stored connection from GscConnectionRepository, builds requests using the search analytics utilities, creates a client via createGscClient, and executes the API call. All errors bubble up as the typed error classes defined in gscErrors.ts.
import { GscService } from '@/server/features/gsc/services/GscService';
async function getPerformanceExample(projectId: string) {
const perf = await GscService.getPerformance({
projectId,
dimensions: ['query'],
dateRange: 'last_7_days',
});
console.log('Site URL:', perf.siteUrl);
console.log('Rows returned:', perf.rows.length);
}
Integration Flow: How the Utilities Work Together
Understanding the relationship between these modules clarifies the data flow when a user requests GSC data:
-
UI components import
GSC_OAUTH_PROVIDER_IDandGSC_OAUTH_SCOPESfromsrc/shared/gsc.tsto render the "Connect GSC" button using Better Auth. -
When executing a tool,
GscServicechecks for an existing connection in the repository. If none exists, it throwsGscNotConnectedError. -
Token retrieval happens inside
createGscClient, which fetches credentials and prepares authenticated headers. -
Request shaping occurs in
buildSearchAnalyticsRequest, translating Zod-validated MCP inputs into GSC API parameters including dimension filter groups. -
Error classification ensures that API failures become
GscApiError, token issues becomeGscTokenError, and missing connections remainGscNotConnectedError, allowing the MCP layer to render appropriate user guidance.
import {
GscApiError,
GscTokenError,
GscNotConnectedError,
} from '@/server/lib/gscErrors';
try {
await GscService.getPerformance({ projectId: 'proj_123' });
} catch (e) {
if (e instanceof GscNotConnectedError) {
console.warn('Project has no GSC connection – prompt the user to connect.');
} else if (e instanceof GscTokenError) {
console.warn('Token expired or revoked – ask the user to reconnect.');
} else if (e instanceof GscApiError) {
console.error(`GSC API returned ${e.status}: ${e.message}`);
}
}
Summary
src/shared/gsc.tsexports OAuth constants likeGSC_OAUTH_PROVIDER_IDandGSC_OAUTH_SCOPESfor use in both server authentication and client UI components.createGscClientinsrc/server/lib/gscClient.tsmanages token retrieval viagetAuth().api.getAccessTokenand provides authenticated methods forlistSites,querySearchAnalytics, andinspectUrl.- Typed error classes (
GscApiError,GscTokenError,GscNotConnectedError) enable granular error handling strategies throughout the application. - Pure helper functions like
buildSearchAnalyticsRequestandresolveDateRangetranslate high-level inputs into GSC API-compatible request shapes. GscService.tsorchestrates the entire integration flow, combining repository access, client instantiation, and error bubbling for consistent project-scoped operations.
Frequently Asked Questions
How does OpenSEO handle GSC authentication tokens?
OpenSEO retrieves GSC access tokens through the createGscClient function in src/server/lib/gscClient.ts, which internally calls getAuth().api.getAccessToken using the user ID and optional Google account ID. This ensures tokens are fetched fresh for each API interaction and properly signed for Google Search Console requests.
What error types should I catch when calling GSC APIs in OpenSEO?
You should catch three specific error classes from src/server/lib/gscErrors.ts: GscNotConnectedError when a project lacks a GSC connection, GscTokenError when authentication tokens expire or are revoked, and GscApiError when the GSC API returns a non-2xx status code. These typed errors allow you to render specific user guidance for each failure mode.
Can I use the GSC utilities outside of the MCP tools?
Yes. The shared utilities are designed for reuse across the entire codebase. You can import createGscClient directly for custom API operations, use buildSearchAnalyticsRequest for manual request construction, or leverage GscService methods in background jobs, scheduled tasks, or custom API routes without duplicating authentication or error-handling logic.
Where are the GSC API constants defined for OAuth configuration?
OAuth-related constants including GSC_OAUTH_PROVIDER_ID, GSC_OAUTH_SCOPES, and GSC_SELF_HOSTED_SETUP_DOCS_URL are defined in src/shared/gsc.ts. This location allows both server-side authentication handlers and client-side UI components to import the same values, ensuring consistency in OAuth flows across the application.
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 →