@power-seo/search-console

Typed Google Search Console API client for TypeScript — OAuth2 and service account auth, auto-paginated search analytics, URL inspection, and sitemap management with zero boilerplate.

@power-seo/search-console is a production-ready Google Search Console API client for TypeScript. Provide OAuth2 credentials or a service account key — get back fully typed search analytics rows, URL inspection verdicts, and sitemap management operations. The token manager handles refresh cycles and JWT signing automatically. querySearchAnalyticsAll() transparently pages through the 25,000-row GSC API limit, merging all results into a single array. Use it in Next.js API routes, Remix loaders, Node.js scripts, and CI/CD pipelines. All operations are server-side only — service account credentials must never be exposed to the browser.
Zero runtime dependencies — pure TypeScript with native fetch and crypto; no googleapis package required.
Why @power-seo/search-console?
| OAuth2 token refresh | ❌ 50+ lines of boilerplate per project | ✅ Auto-refresh via createTokenManager() |
| GSC data pagination | ❌ Manual rowOffset loops and array merging | ✅ querySearchAnalyticsAll() — one call, all rows |
| URL inspection | ❌ Manual GSC UI check only | ✅ Programmatic inspectUrl() in CI pipelines |
| Service accounts | ❌ Complex JWT signing setup | ✅ createTokenManager({ type: 'service-account' }) |
| Type safety | ❌ Raw API responses typed as any | ✅ Fully typed request and response shapes |
| Sitemap management | ❌ Manual GSC UI operations | ✅ submitSitemap(), listSitemaps(), deleteSitemap() |
| Framework support | ❌ Tied to googleapis setup | ✅ Works in Next.js, Remix, Node.js, CI/CD |

Features
- OAuth2 authentication —
createTokenManager({ type: 'oauth' }) handles token refresh automatically
- Service account JWT authentication —
createTokenManager({ type: 'service-account' }) signs JWTs for server-to-server access without user interaction
- Low-level auth primitives —
exchangeRefreshToken() and getServiceAccountToken() for custom auth flows
- Typed GSC client —
createGSCClient(config) returns a GSCClient scoped to a specific verified site URL
- Search analytics —
querySearchAnalytics() supports all 6 dimensions: query, page, country, device, date, searchAppearance
- All search types —
web, image, video, and news search types
- Auto-paginated full fetch —
querySearchAnalyticsAll() merges all pages into one SearchAnalyticsRow[] array
- URL inspection —
inspectUrl() returns verdict, indexing state, last crawl time, mobile usability, and rich result status
- Direct URL inspection —
inspectUrlDirect() for the direct URL inspection API endpoint
- Sitemap listing —
listSitemaps() with status, last download time, and error counts
- Sitemap submission and deletion —
submitSitemap() and deleteSitemap()
- Typed error handling —
GSCApiError class with status, code, and message
- Full TypeScript support — complete type definitions for all request and response shapes

Comparison
| OAuth2 token auto-refresh | ✅ | ✅ | ❌ | ✅ |
| Service account JWT signing | ✅ | ✅ | ❌ | ✅ |
| Auto-paginated analytics fetch | ❌ | ❌ | ❌ | ✅ |
| Typed GSC-specific response shapes | ❌ | ⚠️ | ❌ | ✅ |
| URL inspection support | ❌ | ⚠️ | ❌ | ✅ |
| Sitemap management | ❌ | ⚠️ | ❌ | ✅ |
| Zero runtime dependencies | ❌ | ❌ | ✅ | ✅ |
| TypeScript-first | ❌ | ⚠️ | ❌ | ✅ |

Installation
npm install @power-seo/search-console
yarn add @power-seo/search-console
pnpm add @power-seo/search-console
Quick Start
import {
createTokenManager,
createGSCClient,
querySearchAnalyticsAll,
} from '@power-seo/search-console';
import { exchangeRefreshToken } from '@power-seo/search-console';
const tokenManager = createTokenManager(() =>
exchangeRefreshToken({
clientId: process.env.GSC_CLIENT_ID!,
clientSecret: process.env.GSC_CLIENT_SECRET!,
refreshToken: process.env.GSC_REFRESH_TOKEN!,
}),
);
const client = createGSCClient({
siteUrl: 'https://example.com',
auth: tokenManager,
});
const rows = await querySearchAnalyticsAll(client, {
startDate: '2026-01-01',
endDate: '2026-01-31',
dimensions: ['query', 'page'],
});
rows.forEach(({ keys, clicks, impressions, ctr, position }) => {
console.log(`Query: "${keys[0]}", Page: ${keys[1]}`);
console.log(` ${clicks} clicks, ${impressions} impressions, pos ${position.toFixed(1)}`);
});

Usage
OAuth2 Authentication
import { createTokenManager, exchangeRefreshToken } from '@power-seo/search-console';
const tokenManager = createTokenManager(() =>
exchangeRefreshToken({
clientId: process.env.GSC_CLIENT_ID!,
clientSecret: process.env.GSC_CLIENT_SECRET!,
refreshToken: process.env.GSC_REFRESH_TOKEN!,
}),
);
const accessToken = await tokenManager.getToken();
Service Account Authentication
import { createTokenManager, getServiceAccountToken } from '@power-seo/search-console';
import { subtle } from 'node:crypto';
const serviceAccount = JSON.parse(process.env.GSC_SERVICE_ACCOUNT_JSON!);
async function signJwt(payload: Record<string, unknown>): Promise<string> {
}
const tokenManager = createTokenManager(() =>
getServiceAccountToken({
clientEmail: serviceAccount.client_email,
privateKeyId: serviceAccount.private_key_id,
signJwt,
}),
);
Search Analytics Query
import { createGSCClient, querySearchAnalytics } from '@power-seo/search-console';
const client = createGSCClient({ siteUrl: 'https://example.com', tokenManager });
const response = await querySearchAnalytics(client, {
startDate: '2026-01-01',
endDate: '2026-01-31',
dimensions: ['query', 'country'],
searchType: 'web',
rowLimit: 5000,
});
Auto-Paginated Full Fetch
import { querySearchAnalyticsAll } from '@power-seo/search-console';
const allRows = await querySearchAnalyticsAll(client, {
startDate: '2026-01-01',
endDate: '2026-01-31',
dimensions: ['query'],
});
console.log(`Total rows: ${allRows.length}`);
URL Inspection
import { inspectUrl } from '@power-seo/search-console';
const result = await inspectUrl(client, 'https://example.com/blog/my-post');
console.log(result.verdict);
console.log(result.indexingState);
console.log(result.lastCrawlTime);
console.log(result.mobileUsabilityResult.verdict);
Sitemap Management
import { listSitemaps, submitSitemap, deleteSitemap } from '@power-seo/search-console';
const sitemaps = await listSitemaps(client);
await submitSitemap(client, 'https://example.com/sitemap.xml');
await deleteSitemap(client, 'https://example.com/old-sitemap.xml');
CI/CD Keyword Position Check
import {
createTokenManager,
createGSCClient,
querySearchAnalyticsAll,
getServiceAccountToken,
} from '@power-seo/search-console';
import { subtle } from 'node:crypto';
const serviceAccount = JSON.parse(process.env.GSC_SERVICE_ACCOUNT_JSON!);
async function signJwt(payload: Record<string, unknown>): Promise<string> {
throw new Error('Implement JWT signing');
}
const tokenManager = createTokenManager(() =>
getServiceAccountToken({
clientEmail: serviceAccount.client_email,
privateKeyId: serviceAccount.private_key_id,
signJwt,
}),
);
const client = createGSCClient({ siteUrl: 'sc-domain:example.com', tokenManager });
const rows = await querySearchAnalyticsAll(client, {
startDate: '2026-01-24',
endDate: '2026-01-31',
dimensions: ['query', 'page'],
});
const dropped = rows.filter((r) => r.position > 20 && r.impressions > 100);
if (dropped.length > 0) {
console.error('Pages dropped below position 20:');
dropped.forEach((r) => console.error(' -', r.keys[1], `pos ${r.position.toFixed(1)}`));
process.exit(1);
}
API Reference
createTokenManager(fetchToken)
fetchToken | () => Promise<TokenResult> | Function that returns token result |
Returns TokenManager: { getToken(): Promise<string>; invalidate(): void }. Token caching and refresh is handled automatically.
createGSCClient(config)
config.siteUrl | string | Verified GSC property URL (sc-domain: prefix for domain properties) |
config.auth | TokenManager | Token manager from createTokenManager() |
config.rateLimitPerMinute | number | Rate limit (default: 1200) |
config.maxRetries | number | Max retries for failed requests (default: 3) |
config.baseUrl | string | Base URL for GSC API (default: official Google endpoint) |
Returns GSCClient.
querySearchAnalytics(client, request)
request.startDate | string | required | YYYY-MM-DD |
request.endDate | string | required | YYYY-MM-DD |
request.dimensions | Dimension[] | [] | 'query', 'page', 'country', 'device', 'date', 'searchAppearance' |
request.searchType | SearchType | 'web' | 'web', 'image', 'video', 'news', 'discover', 'googleNews' |
request.rowLimit | number | 1000 | Rows per request (max 25,000) |
request.startRow | number | 0 | Row offset for pagination |
request.dimensionFilterGroups | object[] | [] | Filter groups to narrow results |
request.aggregationType | string | 'auto' | Aggregation method: 'auto', 'byPage', 'byProperty' |
request.dataState | string | 'all' | Include all or final data: 'all', 'final' |
querySearchAnalyticsAll(client, request)
Same parameters as querySearchAnalytics() but rowLimit and startRow are managed automatically. Returns Promise<SearchAnalyticsRow[]>.
inspectUrl(client, url) / inspectUrlDirect(client, url)
Returns Promise<InspectionResult>: { verdict, indexingState, lastCrawlTime, mobileUsabilityResult, richResultsResult, ... }.
listSitemaps(client) / submitSitemap(client, url) / deleteSitemap(client, url)
listSitemaps() returns Promise<SitemapListResponse>. submitSitemap() and deleteSitemap() return Promise<void>.
Types
OAuthCredentials | { clientId, clientSecret, refreshToken } |
ServiceAccountCredentials | { clientEmail, privateKey, scopes } |
TokenResult | { accessToken: string, expiresAt: number } |
TokenManager | { getToken(): Promise<string>, invalidate(): void } |
GSCClientConfig | { siteUrl: string, tokenManager: TokenManager } |
GSCClient | Scoped API client instance |
SearchType | 'web' | 'image' | 'video' | 'news' |
Dimension | 'query' | 'page' | 'country' | 'device' | 'date' | 'searchAppearance' |
SearchAnalyticsRequest | Request shape for querySearchAnalytics() |
SearchAnalyticsRow | { keys: string[], clicks, impressions, ctr, position } |
SearchAnalyticsResponse | API response wrapper with rows: SearchAnalyticsRow[] |
InspectionResult | URL inspection verdict, indexing state, and details |
SitemapEntry | Single sitemap with status, lastDownloaded, errors |
SitemapListResponse | { sitemap: SitemapEntry[] } |
GSCApiError | Error class with status, code, and message |
Use Cases
- Automated keyword ranking reports — fetch all queries weekly and diff against the previous week
- Indexing health monitoring —
inspectUrl() after deployments to verify new pages are indexed
- Content gap analysis — merge GSC data with
@power-seo/analytics to find high-impression, low-click pages
- Sitemap automation — submit new sitemaps programmatically after content migrations
- CI/CD SEO checks — fail pipelines when key pages drop below a position threshold
- Multi-site SaaS dashboards — aggregate GSC data across multiple client properties with one
GSCClient per site
- Image and news search analytics — query
image and news search types separately
- Country and device breakdowns — segment click data by country or device for regional SEO analysis
Architecture Overview
- Pure TypeScript — no compiled binary, no native modules
- Server-side only — requires
crypto for JWT signing; not edge or browser compatible
- Zero runtime dependencies — no googleapis package; uses native
fetch and crypto
- Auto-pagination —
querySearchAnalyticsAll() manages rowOffset and array merging transparently
- Token caching — access tokens are cached and reused until 5 minutes before expiry
- Scoped clients — each
GSCClient is scoped to one verified GSC property via siteUrl
- Typed errors —
GSCApiError carries HTTP status, error code, and message for reliable error handling
- Dual ESM + CJS — ships both formats via tsup for any bundler or
require() usage
Supply Chain Security
- No install scripts (
postinstall, preinstall)
- No runtime network access outside of GSC API calls
- No
eval or dynamic code execution
- CI-signed builds — all releases published via verified
github.com/CyberCraftBD/power-seo workflow
- Safe for Node.js 18+ server environments
All 17 packages are independently installable — use only what you need.
@power-seo/core | npm i @power-seo/core | Framework-agnostic utilities, types, validators, and constants |
@power-seo/react | npm i @power-seo/react | React SEO components — meta, Open Graph, Twitter Card, breadcrumbs |
@power-seo/meta | npm i @power-seo/meta | SSR meta helpers for Next.js App Router, Remix v2, and generic SSR |
@power-seo/schema | npm i @power-seo/schema | Type-safe JSON-LD structured data — 23 builders + 21 React components |
@power-seo/content-analysis | npm i @power-seo/content-analysis | Yoast-style SEO content scoring engine with React components |
@power-seo/readability | npm i @power-seo/readability | Readability scoring — Flesch-Kincaid, Gunning Fog, Coleman-Liau, ARI |
@power-seo/preview | npm i @power-seo/preview | SERP, Open Graph, and Twitter/X Card preview generators |
@power-seo/sitemap | npm i @power-seo/sitemap | XML sitemap generation, streaming, index splitting, and validation |
@power-seo/redirects | npm i @power-seo/redirects | Redirect engine with Next.js, Remix, and Express adapters |
@power-seo/links | npm i @power-seo/links | Link graph analysis — orphan detection, suggestions, equity scoring |
@power-seo/audit | npm i @power-seo/audit | Full SEO audit engine — meta, content, structure, performance rules |
@power-seo/images | npm i @power-seo/images | Image SEO — alt text, lazy loading, format analysis, image sitemaps |
@power-seo/ai | npm i @power-seo/ai | LLM-agnostic AI prompt templates and parsers for SEO tasks |
@power-seo/analytics | npm i @power-seo/analytics | Merge GSC + audit data, trend analysis, ranking insights, dashboard |
@power-seo/search-console | npm i @power-seo/search-console | Google Search Console API — OAuth2, service account, URL inspection |
@power-seo/integrations | npm i @power-seo/integrations | Semrush and Ahrefs API clients with rate limiting and pagination |
@power-seo/tracking | npm i @power-seo/tracking | GA4, Clarity, PostHog, Plausible, Fathom — scripts + consent management |
CyberCraft Bangladesh is a Bangladesh-based enterprise-grade software development and Full Stack SEO service provider company specializing in ERP system development, AI-powered SaaS and business applications, full-stack SEO services, custom website development, and scalable eCommerce platforms. We design and develop intelligent, automation-driven SaaS and enterprise solutions that help startups, SMEs, NGOs, educational institutes, and large organizations streamline operations, enhance digital visibility, and accelerate growth through modern cloud-native technologies.

© 2026 CyberCraft Bangladesh · Released under the MIT License