How to Connect Google Search Console to OpenSEO: Complete Integration Guide
Connect Google Search Console to OpenSEO via OAuth, select a property, and unlock the Search Performance and URL Inspection MCP tools.
OpenSEO integrates Google Search Console (GSC) as an optional data source that powers the Search Performance and URL Inspection tools. This guide explains how to connect Google Search Console to OpenSEO based on the source code in every-app/open-seo, covering both hosted deployments and self-hosted installations.
Architecture Overview
The GSC integration consists of several coordinated components defined in the OpenSEO source code:
| Component | Responsibility | Source Location |
|---|---|---|
| OAuth Provider | Identifies the GSC OAuth client and required scopes (openid, email, profile, https://www.googleapis.com/auth/webmasters.readonly) |
src/shared/gsc.ts |
| Self-hosted OAuth Config | Reads GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, and BETTER_AUTH_SECRET from environment variables |
src/server/features/google/oauth-config |
| GscService | Handles all GSC API calls including token management, request building, and error translation | src/server/features/gsc/services/GscService.ts |
| Server Functions | TanStack Server Functions exposed to the frontend for connection management | src/serverFunctions/gsc.ts |
| MCP Tools | Implements get_search_console_performance and inspect_urls commands for the OpenSEO command palette |
src/server/mcp/tools/search-console-tools.ts |
When any GSC-related MCP tool is invoked, the handler first checks missingSelfHostedGoogleClientResponse. For self-hosted deployments missing OAuth configuration, the user receives a message containing GSC_SELF_HOSTED_SETUP_DOCS_URL from src/shared/gsc.ts.
Connection Methods: Hosted vs. Self-Hosted
Hosted Version (Every App Managed)
Users on the hosted version require no environment configuration. The OAuth provider is pre-configured by Every App.
To connect Google Search Console to OpenSEO:
- Navigate to your project's Integrations settings
- Click Connect Search Console
- Authenticate with Google and authorize the Webmasters Read-only scope
- Select a property from your available GSC sites
Self-Hosted Version
Self-hosted deployments require manual OAuth configuration before users can connect.
Step 1: Configure Environment Variables
Set these variables in your OpenSEO instance:
GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret
BETTER_AUTH_SECRET=your-better-auth-secret
The hasSelfHostedGoogleOAuthConfig helper in src/server/features/google/oauth-config validates these values. If missing, the UI displays setup nudges pointing to GSC_SELF_HOSTED_SETUP_DOCS_URL.
Step 2: Initiate OAuth Flow
From a client component, call startSelfHostedGscLink:
// Called when the user clicks "Connect Search Console"
await startSelfHostedGscLink({
callbackURL: `${window.location.origin}/auth/callback`,
}).then((resp) => {
// Redirect the user to the Google consent screen
window.location.href = resp.url;
});
Step 3: Complete Authentication
After Google redirects to your callback URL, the server stores the access and refresh tokens linked to the user's Better Auth account. The GscService class manages token refresh automatically.
Selecting and Binding a GSC Property
Once authenticated, users must bind a specific GSC property to their OpenSEO project.
List Available Sites
Call listGscSites to retrieve accessible properties:
const { accounts } = await listGscSites({ projectId });
accounts.forEach((grant) => {
console.log(`Account ${grant.email} – sites:`);
grant.sites.forEach((site) => {
const status = site.isSelected ? '[selected]' : '';
console.log(` • ${site.siteUrl} (${site.permissionLevel}) ${status}`);
});
});
Bind a Site to the Project
Use setGscSite to create the connection:
await setGscSite({
projectId,
accountId: "<selected-account-id>",
siteUrl: "https://example.com",
});
This creates a row in the gsc table defined in src/db/gsc.schema.ts, storing the accountId, siteUrl, and linking metadata.
Verify Connection Status
Call getGscConnection to confirm the link:
const connection = await getGscConnection({ projectId });
// Returns: { connected: true, siteUrl, connectedByEmail, createdAt, updatedAt }
The Integrations page displays this status to users.
Using GSC Data: MCP Tools
With an active connection, two MCP tools become available in the OpenSEO command palette.
Search Performance Tool
The get_search_console_performance tool queries GSC analytics data:
await getSearchConsolePerformanceTool.handler({
projectId,
dimensions: ["query", "page"],
dateRange: "last_28_days",
});
Response includes:
rows— array of performance data with clicks, impressions, CTR, and positionhasMore— pagination flagtext— human-readable summary for UI display
Valid dimensions: query, page, country, device, searchAppearance. Valid date ranges: last_7_days, last_28_days, last_3_months, last_6_months, last_year, last_12_months.
URL Inspection Tool
The inspect_urls tool checks indexing status for specific URLs:
await inspectUrlsTool.handler({
projectId,
urls: ["https://example.com/blog/post"],
});
Response includes per URL:
verdict— overall statuscoverageState— indexing statecanonical— canonical URL information
Error Handling
The describeGscError function in GscService.ts normalizes errors into user-friendly messages:
| Error Type | Cause | User Action |
|---|---|---|
GscNotConnectedError |
No property bound to project | Visit /p/:projectId/search-performance to connect |
GscTokenError |
Expired or revoked token | Re-authenticate via OAuth flow |
GscApiError |
GSC API failure | Retry or check Google status |
All errors include a Connect URL redirecting to the project's Search Performance dashboard.
Key Source Files
Reference these files when extending or debugging the GSC integration:
src/shared/gsc.ts— OAuth scopes, provider ID, and documentation URL constantssrc/server/features/gsc/services/GscService.ts— Core API client with token handlingsrc/serverFunctions/gsc.ts— TanStack Server Functions for connection managementsrc/server/mcp/tools/search-console-tools.ts— Search Performance and URL Inspection command implementationssrc/db/gsc.schema.ts— Database schema for GSC connection persistence
Summary
- Hosted deployments require zero configuration—users connect directly via OAuth
- Self-hosted deployments need
GOOGLE_CLIENT_ID,GOOGLE_CLIENT_SECRET, andBETTER_AUTH_SECRETenvironment variables - The connection flow follows: OAuth grant → token storage → site selection → project binding
GscService.tsabstracts all GSC API interactions with automatic token refresh- Two MCP tools expose GSC data:
get_search_console_performanceandinspect_urls - Error states redirect users to
/p/:projectId/search-performancefor reconnection
Frequently Asked Questions
What's the difference between hosted and self-hosted GSC connection?
Hosted OpenSEO (managed by Every App) includes pre-configured OAuth credentials. Self-hosted instances require you to create a Google OAuth client and set GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, and BETTER_AUTH_SECRET environment variables. The hasSelfHostedGoogleOAuthConfig check in src/server/features/google/oauth-config determines which flow executes.
What Google OAuth scopes does OpenSEO require?
OpenSEO requests openid, email, profile, and https://www.googleapis.com/auth/webmasters.readonly. The read-only Webmasters scope is defined in src/shared/gsc.ts as GSC_OAUTH_PROVIDER_ID. No write access to your Search Console properties is requested.
Can users connect multiple GSC properties to one OpenSEO project?
No—each OpenSEO project binds to exactly one GSC property via the setGscSite function, which creates a single row in the gsc table. Users with access to multiple GSC accounts can view all available sites through listGscSites, but must select one per 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →