Skip to content

@vitabletech/gbp-sdk


@vitabletech/gbp-sdk ​

Enterprise-grade Google Business Profile (GBP) SDK for Node.js, Next.js, and TypeScript.

NPM VersionLicenseTypeScriptInteractive Playground

⚡ Try the Live Playground & API Explorer ​

Want to test the Google Business Profile APIs without writing code or setting up a local server?
👉 https://gbp-playground.vitabletech.in
Test OAuth 2.0 (BYOC), Locations, Performance Metrics v1, Reviews, Verifications, and Quotas with real-time interactive Swagger documentation.



Features ​

  • Automatic Token Management: Automatically handles refreshing access tokens when they expire. Thread-safe to prevent duplicate refresh requests.
  • Pluggable Token Storage: Supports memory, file, and custom token storage implementations (e.g. Redis).
  • Robust HTTP Client: Built-in exponential backoff, retry logic for 429 and 5xx errors, and rate limit handling.
  • Auto-Pagination: Provides listAll methods and cursor paginators to automatically traverse nextPageToken and fetch all records.
  • Performance & Metrics API (v1): First-class native support for daily metric time series, multi-metric queries, and monthly search keyword impression counts.
  • Strong Typing: Full TypeScript support with generics.
  • Generic Requests: Exposes a request() method for unsupported or newly released Google APIs.

Installation ​

bash
npm install @vitabletech/gbp-sdk

Network Whitelist ​

If you are running this SDK behind a strict corporate firewall, please ensure you whitelist the necessary Google API domains. See the Network Whitelist Documentation for the complete list of domains and URLs.

What's New in v1.3.0 🎉 ​

  • Business Profile Performance API (v1): Full native integration with businessprofileperformance.googleapis.com via MetricsService and direct client.locations shortcuts.
  • Daily Metrics Time Series: New locations.getDailyMetricsTimeSeries method to fetch daily counts for calls, website clicks, directions, bookings, food orders, and impressions.
  • Multi Daily Metrics Time Series: Enhanced locations.fetchMultiDailyMetricsTimeSeries with support for sub-entity breakdowns (dailySubEntityType) and both camelCase (startDate/endDate) & snake_case dates.
  • Monthly Search Keyword Impressions: Track customer search terms with locations.searchkeywords.impressions.monthly.list / listSearchKeywordsImpressionsMonthly.
  • Auto-Pagination for Keywords: Built-in listAllSearchKeywordsImpressionsMonthly and listSearchKeywordsImpressionsMonthlyPaginator.
  • Performance Quotas: Direct client.quotas.getPerformance(projectId) to monitor Performance API rate limits and quotas.

What's New in v1.0.0 🎉 ​

  • Native Location Attributes: Added native getAttributes and patchAttributes support to LocationsService.
  • Enhanced Media Uploads: Upgraded MediaService to fully support Google's v4 endpoints by allowing direct accountId binding.
  • Verifications API: Added full native support for the mybusinessverifications.googleapis.com API via the new VerificationsService.
  • Quotas API: Programmatically check Google Cloud Service Usage Quotas for Business Profile APIs (serviceusage.googleapis.com) to avoid hitting rate limits.
  • Chains API: Find global brands and associate your locations with them easily via ChainsService.
  • Network Whitelisting: Added comprehensive network whitelist documentation for enterprise users.
  • Food Menus & Metrics Types: Added complete, strict TypeScript interfaces for the Google Business Profile FoodMenus and Metrics APIs.
  • Quota Management: Check API quotas and limits using QuotasService without risking hitting limits unexpectedly.

Quick Start ​

typescript
import { GBPClient, ConsoleLogger } from '@vitabletech/gbp-sdk';

const client = new GBPClient({
  clientId: 'YOUR_GOOGLE_CLIENT_ID',
  clientSecret: 'YOUR_GOOGLE_CLIENT_SECRET',
  refreshToken: 'YOUR_REFRESH_TOKEN',
  tokenStorage: 'file', // stores tokens in gbp-tokens.json
  logger: new ConsoleLogger(), // optional pluggable logger
});

async function main() {
  // Automatically handles token generation and pagination!
  const accounts = await client.accounts.listAll();

  if (accounts.length > 0) {
    const accountName = accounts[0].name;
    const locations = await client.locations.listAll(accountName);

    console.log(`Found ${locations.length} locations for ${accountName}`);
  }
}

main();

Fetching Performance Metrics & Search Keywords ​

typescript
import { DailyMetric } from '@vitabletech/gbp-sdk';

// 1. Fetch daily metrics time series (e.g. Website Clicks)
const dailyClicks = await client.locations.getDailyMetricsTimeSeries(
  'locations/12345',
  {
    dailyMetric: DailyMetric.WEBSITE_CLICKS,
    dailyRange: {
      startDate: { year: 2024, month: 1, day: 1 },
      endDate: { year: 2024, month: 1, day: 31 },
    },
  }
);

// 2. Fetch monthly search keywords with auto-pagination
const keywords = await client.locations.listAllSearchKeywordsImpressionsMonthly(
  'locations/12345',
  {
    monthlyRange: {
      startMonth: { year: 2024, month: 1 },
      endMonth: { year: 2024, month: 3 },
    },
  }
);

Creating a Location Example Payload ​

When using client.locations.create(), you must pass a valid location object. Here is an example of a complete payload:

json
{
  "languageCode": "en",
  "title": "Your Shop Name",
  "storeCode": "1234567",
  "phoneNumbers": {
    "primaryPhone": "+9112345678902"
  },
  "categories": {
    "primaryCategory": {
      "name": "categories/gcid:airport"
    }
  },
  "storefrontAddress": {
    "regionCode": "IN",
    "postalCode": "123456",
    "administrativeArea": "State Name",
    "locality": "City Name",
    "addressLines": ["Address Line 1", "Address Line 2"]
  },
  "latlng": {
    "latitude": 34.521721,
    "longitude": 92.519443
  },
  "websiteUri": "https://www.yourwebsite.in",
  "regularHours": {
    "periods": [
      {
        "openDay": "MONDAY",
        "openTime": { "hours": 6, "minutes": 0 },
        "closeDay": "MONDAY",
        "closeTime": { "hours": 22, "minutes": 0 }
      },
      {
        "openDay": "TUESDAY",
        "openTime": { "hours": 6, "minutes": 0 },
        "closeDay": "TUESDAY",
        "closeTime": { "hours": 22, "minutes": 0 }
      },
      {
        "openDay": "WEDNESDAY",
        "openTime": { "hours": 6, "minutes": 0 },
        "closeDay": "WEDNESDAY",
        "closeTime": { "hours": 22, "minutes": 0 }
      },
      {
        "openDay": "THURSDAY",
        "openTime": { "hours": 6, "minutes": 0 },
        "closeDay": "THURSDAY",
        "closeTime": { "hours": 22, "minutes": 0 }
      },
      {
        "openDay": "FRIDAY",
        "openTime": { "hours": 6, "minutes": 0 },
        "closeDay": "FRIDAY",
        "closeTime": { "hours": 22, "minutes": 0 }
      },
      {
        "openDay": "SATURDAY",
        "openTime": { "hours": 6, "minutes": 0 },
        "closeDay": "SATURDAY",
        "closeTime": { "hours": 22, "minutes": 0 }
      },
      {
        "openDay": "SUNDAY",
        "openTime": { "hours": 6, "minutes": 0 },
        "closeDay": "SUNDAY",
        "closeTime": { "hours": 22, "minutes": 0 }
      }
    ]
  },
  "profile": {
    "description": "Your RO - Retail Outlet."
  }
}

Reading API Quotas ​

You can programmatically retrieve Google Service Usage quotas using the SDK. This is useful for monitoring limits, such as Location creation limits. Note: this retrieves quota configuration/limits, not necessarily your current usage.

Quota OAuth Scopes ​

Reading quotas requires the https://www.googleapis.com/auth/cloud-platform.read-only scope in addition to the standard business.manage scope. Also, the user must have appropriate IAM permissions on the target Google Cloud project to read quotas.

Important: If you add enableQuotaAccess, existing authorized users may need to re-consent to grant the new scope.

typescript
const client = new GBPClient({
  clientId: process.env.GOOGLE_CLIENT_ID,
  clientSecret: process.env.GOOGLE_CLIENT_SECRET,
  refreshToken: process.env.GOOGLE_REFRESH_TOKEN,
  enableQuotaAccess: true, // Opt-in to request the quota scope during OAuth flow
});

async function checkQuotas() {
  const quotas = await client.quotas.get({
    projectId: 'YOUR_PROJECT_ID_OR_NUMBER',
    service: 'mybusinessbusinessinformation.googleapis.com',
  });

  console.log(quotas.quotas);
  // [ { metric: '...', displayName: 'Create Location requests per day', limit: 100, unit: '1/d' } ]
}

Generic Request Mechanism ​

You can use the generic request() method to interact with endpoints not yet natively wrapped by the SDK:

typescript
const response = await client.request({
  method: 'GET',
  url: 'https://oauth2.googleapis.com/tokeninfo',
  query: {
    access_token: 'YOUR_ACCESS_TOKEN',
  },
});