Google Business API
Schedule and automate Google Business Profile posts with Zernio API - Updates, CTAs, location management, reviews, and local SEO
Quick Reference
| Property | Value |
|---|---|
| Character limit | 1,500 |
| Images per post | 1 |
| Videos per post | Not supported |
| Image formats | JPEG, PNG only (WebP auto-converted) |
| Image max size | 5 MB |
| Image min dimensions | 400 x 300 px |
| Post types | Text, Text+Image, Text+CTA, Event, Offer |
| Scheduling | Yes |
| Inbox (Reviews) | Yes (add-on) |
| Inbox (DMs/Comments) | No |
| Analytics | Location-level only (per-post deprecated by Google) |
Before You Start
Google Business Profile is not social media -- it's local SEO. Posts appear on Google Search, Google Maps, and Google Knowledge Panel. They contribute to local search ranking. Posts are visible for about 7 days before being archived. Post weekly minimum.
- Requires a verified Google Business Profile
- Posts appear in Google Search + Maps (not a social feed)
- Videos are not supported
- No text-only posts via API (media or CTA recommended for visibility)
Quick Start
Create a Google Business Profile post with an image:
const { post } = await zernio.posts.createPost({
content: 'We are open this holiday weekend! Stop by for our special seasonal menu.',
mediaItems: [
{ type: 'image', url: 'https://example.com/holiday-special.jpg' }
],
platforms: [
{ platform: 'googlebusiness', accountId: 'YOUR_ACCOUNT_ID' }
],
publishNow: true
});
console.log('Posted to Google Business!', post._id);result = client.posts.create(
content="We are open this holiday weekend! Stop by for our special seasonal menu.",
media_items=[
{"type": "image", "url": "https://example.com/holiday-special.jpg"}
],
platforms=[
{"platform": "googlebusiness", "accountId": "YOUR_ACCOUNT_ID"}
],
publish_now=True
)
post = result.post
print(f"Posted to Google Business! {post['_id']}")curl -X POST https://zernio.com/api/v1/posts \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "We are open this holiday weekend! Stop by for our special seasonal menu.",
"mediaItems": [
{"type": "image", "url": "https://example.com/holiday-special.jpg"}
],
"platforms": [
{"platform": "googlebusiness", "accountId": "YOUR_ACCOUNT_ID"}
],
"publishNow": true
}'Content Types
Text + Image Post
The most common and recommended post type. A single image with text. No contentType field is needed -- this is the default when media is included.
const { post } = await zernio.posts.createPost({
content: 'Fresh seasonal menu available now! Visit us to try our new dishes.',
mediaItems: [
{ type: 'image', url: 'https://example.com/seasonal-menu.jpg' }
],
platforms: [
{ platform: 'googlebusiness', accountId: 'YOUR_ACCOUNT_ID' }
],
publishNow: true
});result = client.posts.create(
content="Fresh seasonal menu available now! Visit us to try our new dishes.",
media_items=[
{"type": "image", "url": "https://example.com/seasonal-menu.jpg"}
],
platforms=[
{"platform": "googlebusiness", "accountId": "YOUR_ACCOUNT_ID"}
],
publish_now=True
)curl -X POST https://zernio.com/api/v1/posts \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "Fresh seasonal menu available now! Visit us to try our new dishes.",
"mediaItems": [
{"type": "image", "url": "https://example.com/seasonal-menu.jpg"}
],
"platforms": [
{"platform": "googlebusiness", "accountId": "YOUR_ACCOUNT_ID"}
],
"publishNow": true
}'Text-Only Post
Text-only posts are supported but have lower visibility on Google Search and Maps. Adding an image or CTA is recommended.
const { post } = await zernio.posts.createPost({
content: 'Happy Friday! We are offering 20% off all services this weekend. Mention this post when you visit!',
platforms: [
{ platform: 'googlebusiness', accountId: 'YOUR_ACCOUNT_ID' }
],
publishNow: true
});result = client.posts.create(
content="Happy Friday! We are offering 20% off all services this weekend. Mention this post when you visit!",
platforms=[
{"platform": "googlebusiness", "accountId": "YOUR_ACCOUNT_ID"}
],
publish_now=True
)curl -X POST https://zernio.com/api/v1/posts \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "Happy Friday! We are offering 20% off all services this weekend. Mention this post when you visit!",
"platforms": [
{"platform": "googlebusiness", "accountId": "YOUR_ACCOUNT_ID"}
],
"publishNow": true
}'Post with CTA Button
Add a call-to-action button to drive traffic. The CTA appears as a prominent button below the post content.
const { post } = await zernio.posts.createPost({
content: 'Book your appointment today! Limited spots available this week.',
mediaItems: [
{ type: 'image', url: 'https://example.com/booking.jpg' }
],
platforms: [{
platform: 'googlebusiness',
accountId: 'YOUR_ACCOUNT_ID',
platformSpecificData: {
callToAction: {
type: 'BOOK',
url: 'https://mybusiness.com/book'
}
}
}],
publishNow: true
});result = client.posts.create(
content="Book your appointment today! Limited spots available this week.",
media_items=[
{"type": "image", "url": "https://example.com/booking.jpg"}
],
platforms=[{
"platform": "googlebusiness",
"accountId": "YOUR_ACCOUNT_ID",
"platformSpecificData": {
"callToAction": {
"type": "BOOK",
"url": "https://mybusiness.com/book"
}
}
}],
publish_now=True
)curl -X POST https://zernio.com/api/v1/posts \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "Book your appointment today! Limited spots available this week.",
"mediaItems": [
{"type": "image", "url": "https://example.com/booking.jpg"}
],
"platforms": [{
"platform": "googlebusiness",
"accountId": "YOUR_ACCOUNT_ID",
"platformSpecificData": {
"callToAction": {
"type": "BOOK",
"url": "https://mybusiness.com/book"
}
}
}],
"publishNow": true
}'Available CTA Types:
| Type | Description | Best For |
|---|---|---|
LEARN_MORE | Link to more information | Articles, about pages |
BOOK | Booking/reservation link | Services, appointments |
ORDER | Online ordering link | Restaurants, food |
SHOP | E-commerce link | Retail, products |
SIGN_UP | Registration link | Events, newsletters |
CALL | Phone call action | Contact, inquiries |
Event Post
Promote an event with a title, date range, and optional CTA. Events appear prominently on your Google listing with the event title and schedule.
const { post } = await zernio.posts.createPost({
content: 'Join us for our Grand Opening Weekend! Free samples and live music.',
mediaItems: [
{ type: 'image', url: 'https://example.com/grand-opening.jpg' }
],
platforms: [{
platform: 'googlebusiness',
accountId: 'YOUR_ACCOUNT_ID',
platformSpecificData: {
topicType: 'EVENT',
event: {
title: 'Grand Opening Weekend',
schedule: {
startDate: { year: 2026, month: 5, day: 15 },
startTime: { hours: 9, minutes: 0 },
endDate: { year: 2026, month: 5, day: 16 },
endTime: { hours: 17, minutes: 0 }
}
},
callToAction: {
type: 'LEARN_MORE',
url: 'https://mybusiness.com/grand-opening'
}
}
}],
publishNow: true
});result = client.posts.create(
content="Join us for our Grand Opening Weekend! Free samples and live music.",
media_items=[
{"type": "image", "url": "https://example.com/grand-opening.jpg"}
],
platforms=[{
"platform": "googlebusiness",
"accountId": "YOUR_ACCOUNT_ID",
"platformSpecificData": {
"topicType": "EVENT",
"event": {
"title": "Grand Opening Weekend",
"schedule": {
"startDate": {"year": 2026, "month": 5, "day": 15},
"startTime": {"hours": 9, "minutes": 0},
"endDate": {"year": 2026, "month": 5, "day": 16},
"endTime": {"hours": 17, "minutes": 0}
}
},
"callToAction": {
"type": "LEARN_MORE",
"url": "https://mybusiness.com/grand-opening"
}
}
}],
publish_now=True
)curl -X POST https://zernio.com/api/v1/posts \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "Join us for our Grand Opening Weekend! Free samples and live music.",
"mediaItems": [
{"type": "image", "url": "https://example.com/grand-opening.jpg"}
],
"platforms": [{
"platform": "googlebusiness",
"accountId": "YOUR_ACCOUNT_ID",
"platformSpecificData": {
"topicType": "EVENT",
"event": {
"title": "Grand Opening Weekend",
"schedule": {
"startDate": {"year": 2026, "month": 5, "day": 15},
"startTime": {"hours": 9, "minutes": 0},
"endDate": {"year": 2026, "month": 5, "day": 16},
"endTime": {"hours": 17, "minutes": 0}
}
},
"callToAction": {
"type": "LEARN_MORE",
"url": "https://mybusiness.com/grand-opening"
}
}
}],
"publishNow": true
}'Schedule dates also accept ISO 8601 strings, which are converted automatically:
{
"topicType": "EVENT",
"event": {
"title": "Grand Opening Weekend",
"schedule": {
"startDate": "2026-05-15T00:00:00Z",
"startTime": "2026-05-15T09:00:00Z",
"endDate": "2026-05-16T00:00:00Z",
"endTime": "2026-05-16T17:00:00Z"
}
}
}Offer Post
Promote a deal with coupon codes, redemption URLs, and terms. Offer posts include an event object that sets the offer period and title displayed on Google.
const { post } = await zernio.posts.createPost({
content: 'Holiday sale! 20% off everything through the end of December.',
mediaItems: [
{ type: 'image', url: 'https://example.com/holiday-sale.jpg' }
],
platforms: [{
platform: 'googlebusiness',
accountId: 'YOUR_ACCOUNT_ID',
platformSpecificData: {
topicType: 'OFFER',
event: {
title: 'Holiday Sale - 20% Off',
schedule: {
startDate: { year: 2026, month: 12, day: 1 },
endDate: { year: 2026, month: 12, day: 31 }
}
},
offer: {
couponCode: 'HOLIDAY20',
redeemOnlineUrl: 'https://mybusiness.com/shop',
termsConditions: 'Valid in-store and online. Cannot be combined with other offers.'
}
}
}],
publishNow: true
});result = client.posts.create(
content="Holiday sale! 20% off everything through the end of December.",
media_items=[
{"type": "image", "url": "https://example.com/holiday-sale.jpg"}
],
platforms=[{
"platform": "googlebusiness",
"accountId": "YOUR_ACCOUNT_ID",
"platformSpecificData": {
"topicType": "OFFER",
"event": {
"title": "Holiday Sale - 20% Off",
"schedule": {
"startDate": {"year": 2026, "month": 12, "day": 1},
"endDate": {"year": 2026, "month": 12, "day": 31}
}
},
"offer": {
"couponCode": "HOLIDAY20",
"redeemOnlineUrl": "https://mybusiness.com/shop",
"termsConditions": "Valid in-store and online. Cannot be combined with other offers."
}
}
}],
publish_now=True
)curl -X POST https://zernio.com/api/v1/posts \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "Holiday sale! 20% off everything through the end of December.",
"mediaItems": [
{"type": "image", "url": "https://example.com/holiday-sale.jpg"}
],
"platforms": [{
"platform": "googlebusiness",
"accountId": "YOUR_ACCOUNT_ID",
"platformSpecificData": {
"topicType": "OFFER",
"event": {
"title": "Holiday Sale - 20% Off",
"schedule": {
"startDate": {"year": 2026, "month": 12, "day": 1},
"endDate": {"year": 2026, "month": 12, "day": 31}
}
},
"offer": {
"couponCode": "HOLIDAY20",
"redeemOnlineUrl": "https://mybusiness.com/shop",
"termsConditions": "Valid in-store and online. Cannot be combined with other offers."
}
}
}],
"publishNow": true
}'Offer fields (all optional, but at least one recommended):
| Field | Type | Description |
|---|---|---|
couponCode | string | Promo code customers can use |
redeemOnlineUrl | string (URI) | URL where the offer can be redeemed |
termsConditions | string | Terms and conditions text |
Media Requirements
| Property | Requirement |
|---|---|
| Max images | 1 per post |
| Formats | JPEG, PNG (WebP auto-converted) |
| Max file size | 5 MB |
| Min dimensions | 400 x 300 px |
| Recommended | 1200 x 900 px (4:3) |
Google may crop images. Use 4:3 aspect ratio for best results.
Platform-Specific Fields
All fields are set inside platformSpecificData on the platform entry.
| Field | Type | Description |
|---|---|---|
topicType | "STANDARD" | "EVENT" | "OFFER" | Post type. Defaults to STANDARD. EVENT requires the event object. OFFER requires offer and optionally event for the offer period. |
event | object | Event details. Required for EVENT, optional for OFFER (sets offer period). Contains title (string) and schedule with startDate, startTime, endDate, endTime. Dates accept { year, month, day } objects or ISO 8601 strings. |
offer | object | Offer details for OFFER posts. Fields: couponCode, redeemOnlineUrl, termsConditions (all optional). |
locationId | string | For multi-location businesses. Format: locations/111111111. Get locations via GET /v1/accounts/{accountId}/gmb-locations. If omitted, posts to default location. |
languageCode | string | BCP 47 language code (e.g., en, de). Sets metadata only -- does not translate content. |
topicType | STANDARD | EVENT | OFFER | ALERT | Post type. STANDARD is a regular update. EVENT requires event. OFFER requires offer. Defaults to STANDARD if omitted. |
callToAction | { type, url } | CTA button. type: LEARN_MORE, BOOK, ORDER, SHOP, SIGN_UP, CALL. url: valid HTTPS URL. |
event | object | Event details. Required when topicType is EVENT. Event schedule accepts both ISO 8601 strings (e.g. 2026-04-15T09:00:00Z) and Google's native { year, month, day } objects. |
offer | object | Offer details. Required when topicType is OFFER. |
Event and Offer Posts (topicType)
Google Business Profile supports three post types via platformSpecificData.topicType:
| topicType | When to use | Required fields |
|---|---|---|
STANDARD | Regular updates | None |
EVENT | Announcements with a date range (grand openings, live music, workshops) | event |
OFFER | Promotions and discounts | offer |
Note: For
EVENTposts, Google returns a 400 error ifeventis omitted.
Event Post Example
const { post } = await zernio.posts.createPost({
content: 'Join us for our Grand Opening Weekend! Food, music, and giveaways.',
mediaItems: [
{ type: 'image', url: 'https://example.com/grand-opening.jpg' }
],
platforms: [{
platform: 'googlebusiness',
accountId: 'YOUR_ACCOUNT_ID',
platformSpecificData: {
topicType: 'EVENT',
event: {
title: 'Grand Opening Weekend',
schedule: {
startDate: { year: 2026, month: 5, day: 15 },
startTime: { hours: 9, minutes: 0 },
endDate: { year: 2026, month: 5, day: 16 },
endTime: { hours: 17, minutes: 0 }
}
},
callToAction: {
type: 'LEARN_MORE',
url: 'https://mybusiness.com/grand-opening'
}
}
}],
publishNow: true
});result = client.posts.create(
content="Join us for our Grand Opening Weekend! Food, music, and giveaways.",
media_items=[
{"type": "image", "url": "https://example.com/grand-opening.jpg"}
],
platforms=[{
"platform": "googlebusiness",
"accountId": "YOUR_ACCOUNT_ID",
"platformSpecificData": {
"topicType": "EVENT",
"event": {
"title": "Grand Opening Weekend",
"schedule": {
"startDate": {"year": 2026, "month": 5, "day": 15},
"startTime": {"hours": 9, "minutes": 0},
"endDate": {"year": 2026, "month": 5, "day": 16},
"endTime": {"hours": 17, "minutes": 0}
}
},
"callToAction": {
"type": "LEARN_MORE",
"url": "https://mybusiness.com/grand-opening"
}
}
}],
publish_now=True
)curl -X POST https://zernio.com/api/v1/posts \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "Join us for our Grand Opening Weekend! Food, music, and giveaways.",
"mediaItems": [
{"type": "image", "url": "https://example.com/grand-opening.jpg"}
],
"platforms": [{
"platform": "googlebusiness",
"accountId": "YOUR_ACCOUNT_ID",
"platformSpecificData": {
"topicType": "EVENT",
"event": {
"title": "Grand Opening Weekend",
"schedule": {
"startDate": {"year": 2026, "month": 5, "day": 15},
"startTime": {"hours": 9, "minutes": 0},
"endDate": {"year": 2026, "month": 5, "day": 16},
"endTime": {"hours": 17, "minutes": 0}
}
},
"callToAction": {
"type": "LEARN_MORE",
"url": "https://mybusiness.com/grand-opening"
}
}
}],
"publishNow": true
}'Offer Post Example
const { post } = await zernio.posts.createPost({
content: 'This weekend only: Save 20% on all services. Use code SAVE20.',
mediaItems: [
{ type: 'image', url: 'https://example.com/save20.jpg' }
],
platforms: [{
platform: 'googlebusiness',
accountId: 'YOUR_ACCOUNT_ID',
platformSpecificData: {
topicType: 'OFFER',
offer: {
offerType: 'OFFER',
redeemOnlineUrl: 'https://mybusiness.com/redeem',
couponCode: 'SAVE20',
termsConditions: 'Valid Fri–Sun only. One per customer.'
},
callToAction: {
type: 'SHOP',
url: 'https://mybusiness.com/services'
}
}
}],
publishNow: true
});result = client.posts.create(
content="This weekend only: Save 20% on all services. Use code SAVE20.",
media_items=[
{"type": "image", "url": "https://example.com/save20.jpg"}
],
platforms=[{
"platform": "googlebusiness",
"accountId": "YOUR_ACCOUNT_ID",
"platformSpecificData": {
"topicType": "OFFER",
"offer": {
"offerType": "OFFER",
"redeemOnlineUrl": "https://mybusiness.com/redeem",
"couponCode": "SAVE20",
"termsConditions": "Valid Fri–Sun only. One per customer."
},
"callToAction": {
"type": "SHOP",
"url": "https://mybusiness.com/services"
}
}
}],
publish_now=True
)curl -X POST https://zernio.com/api/v1/posts \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "This weekend only: Save 20% on all services. Use code SAVE20.",
"mediaItems": [
{"type": "image", "url": "https://example.com/save20.jpg"}
],
"platforms": [{
"platform": "googlebusiness",
"accountId": "YOUR_ACCOUNT_ID",
"platformSpecificData": {
"topicType": "OFFER",
"offer": {
"offerType": "OFFER",
"redeemOnlineUrl": "https://mybusiness.com/redeem",
"couponCode": "SAVE20",
"termsConditions": "Valid Fri–Sun only. One per customer."
},
"callToAction": {
"type": "SHOP",
"url": "https://mybusiness.com/services"
}
}
}],
"publishNow": true
}'Language Code Example
By default, post language is auto-detected from text. If auto-detection may be inaccurate (very short posts, mixed-language content, transliterated text), set languageCode explicitly.
const { post } = await zernio.posts.createPost({
content: 'Diese Woche: 20% Rabatt auf alle Services.',
mediaItems: [
{ type: 'image', url: 'https://example.com/promo.jpg' }
],
platforms: [{
platform: 'googlebusiness',
accountId: 'YOUR_ACCOUNT_ID',
platformSpecificData: {
languageCode: 'de'
}
}],
publishNow: true
});result = client.posts.create(
content="Diese Woche: 20% Rabatt auf alle Services.",
media_items=[
{"type": "image", "url": "https://example.com/promo.jpg"}
],
platforms=[{
"platform": "googlebusiness",
"accountId": "YOUR_ACCOUNT_ID",
"platformSpecificData": {
"languageCode": "de"
}
}],
publish_now=True
)curl -X POST https://zernio.com/api/v1/posts \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "Diese Woche: 20% Rabatt auf alle Services.",
"mediaItems": [
{"type": "image", "url": "https://example.com/promo.jpg"}
],
"platforms": [{
"platform": "googlebusiness",
"accountId": "YOUR_ACCOUNT_ID",
"platformSpecificData": {
"languageCode": "de"
}
}],
"publishNow": true
}'Multi-Location Posting
If your connected Google Business account manages multiple locations, you can post to different locations from the same account connection.
List Available Locations
First, retrieve the list of locations you can post to:
const locations = await zernio.googleBusiness.getLocations('YOUR_ACCOUNT_ID');
console.log('Available locations:', locations);locations = client.google_business.get_locations("YOUR_ACCOUNT_ID")
print("Available locations:", locations)curl -X GET https://zernio.com/api/v1/accounts/YOUR_ACCOUNT_ID/gmb-locations \
-H "Authorization: Bearer YOUR_API_KEY"Post to Multiple Locations
Use the same accountId multiple times with different locationId values:
const { post } = await zernio.posts.createPost({
content: 'Now open at all locations! Visit us today.',
mediaItems: [
{ type: 'image', url: 'https://example.com/store.jpg' }
],
platforms: [
{
platform: 'googlebusiness',
accountId: 'YOUR_ACCOUNT_ID',
platformSpecificData: { locationId: 'locations/111111111' }
},
{
platform: 'googlebusiness',
accountId: 'YOUR_ACCOUNT_ID',
platformSpecificData: { locationId: 'locations/222222222' }
}
],
publishNow: true
});result = client.posts.create(
content="Now open at all locations! Visit us today.",
media_items=[
{"type": "image", "url": "https://example.com/store.jpg"}
],
platforms=[
{
"platform": "googlebusiness",
"accountId": "YOUR_ACCOUNT_ID",
"platformSpecificData": {"locationId": "locations/111111111"}
},
{
"platform": "googlebusiness",
"accountId": "YOUR_ACCOUNT_ID",
"platformSpecificData": {"locationId": "locations/222222222"}
}
],
publish_now=True
)curl -X POST https://zernio.com/api/v1/posts \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "Now open at all locations! Visit us today.",
"mediaItems": [
{"type": "image", "url": "https://example.com/store.jpg"}
],
"platforms": [
{
"platform": "googlebusiness",
"accountId": "YOUR_ACCOUNT_ID",
"platformSpecificData": {
"locationId": "locations/111111111"
}
},
{
"platform": "googlebusiness",
"accountId": "YOUR_ACCOUNT_ID",
"platformSpecificData": {
"locationId": "locations/222222222"
}
}
],
"publishNow": true
}'The locationId format is locations/ followed by the location ID number.
Media URL Requirements
| Requirement | Details |
|---|---|
| Public URL | Must be publicly accessible |
| HTTPS | Secure URLs only |
| No redirects | Direct link to image |
| No auth required | Cannot require login |
https://mybucket.s3.amazonaws.com/image.jpg (valid)
https://example.com/images/post.png (valid)
https://example.com/image?token=abc (invalid - auth required)
http://example.com/image.jpg (invalid - not HTTPS)Business Profile Management
Beyond posting, you can manage your Google Business Profile listing directly through the API. Each subsection below covers a specific management feature.
Food Menus
Manage food menus for locations that support them (restaurants, cafes, etc.). Menu items support price (with currency code), dietaryRestriction (VEGETARIAN, VEGAN, GLUTEN_FREE), allergen (DAIRY, GLUTEN, SHELLFISH), spiciness, servesNumPeople, and preparationMethods.
// Get menus
const menus = await zernio.googleBusiness.getFoodMenus('YOUR_ACCOUNT_ID');
console.log('Food menus:', menus);
// Update menus
await zernio.googleBusiness.updateFoodMenus('YOUR_ACCOUNT_ID', {
menus: [{
labels: [{ displayName: 'Lunch Menu', languageCode: 'en' }],
sections: [{
labels: [{ displayName: 'Appetizers' }],
items: [{
labels: [{ displayName: 'Caesar Salad', description: 'Romaine, parmesan, croutons' }],
attributes: {
price: { currencyCode: 'USD', units: '12' },
dietaryRestriction: ['VEGETARIAN']
}
}]
}]
}],
updateMask: 'menus'
});# Get menus
menus = client.google_business.get_food_menus("YOUR_ACCOUNT_ID")
print("Food menus:", menus)
# Update menus
client.google_business.update_food_menus("YOUR_ACCOUNT_ID",
menus=[{
"labels": [{"displayName": "Lunch Menu", "languageCode": "en"}],
"sections": [{
"labels": [{"displayName": "Appetizers"}],
"items": [{
"labels": [{"displayName": "Caesar Salad", "description": "Romaine, parmesan, croutons"}],
"attributes": {
"price": {"currencyCode": "USD", "units": "12"},
"dietaryRestriction": ["VEGETARIAN"]
}
}]
}]
}],
update_mask="menus"
)# Get menus
curl -X GET https://zernio.com/api/v1/accounts/YOUR_ACCOUNT_ID/gmb-food-menus \
-H "Authorization: Bearer YOUR_API_KEY"
# Update menus
curl -X PUT https://zernio.com/api/v1/accounts/YOUR_ACCOUNT_ID/gmb-food-menus \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"menus": [{
"labels": [{"displayName": "Lunch Menu", "languageCode": "en"}],
"sections": [{
"labels": [{"displayName": "Appetizers"}],
"items": [{
"labels": [{"displayName": "Caesar Salad", "description": "Romaine, parmesan, croutons"}],
"attributes": {
"price": {"currencyCode": "USD", "units": "12"},
"dietaryRestriction": ["VEGETARIAN"]
}
}]
}]
}],
"updateMask": "menus"
}'See the GMB Food Menus API Reference for full schema details.
Location Details
Read and update your business information including hours, special hours, description, phone numbers, and website. Use readMask to request specific fields and updateMask to update them. Available fields include regularHours, specialHours, profile.description, websiteUri, and phoneNumbers.
// Get location details
const details = await zernio.googleBusiness.getLocationDetails('YOUR_ACCOUNT_ID', {
readMask: 'regularHours,specialHours,profile,websiteUri'
});
// Update business hours
await zernio.googleBusiness.updateLocationDetails('YOUR_ACCOUNT_ID', {
updateMask: 'regularHours',
regularHours: {
periods: [
{ openDay: 'MONDAY', openTime: '09:00', closeDay: 'MONDAY', closeTime: '17:00' },
{ openDay: 'TUESDAY', openTime: '09:00', closeDay: 'TUESDAY', closeTime: '17:00' }
]
}
});# Get location details
details = client.google_business.get_location_details("YOUR_ACCOUNT_ID",
read_mask="regularHours,specialHours,profile,websiteUri"
)
# Update business hours
client.google_business.update_location_details("YOUR_ACCOUNT_ID",
update_mask="regularHours",
regular_hours={
"periods": [
{"openDay": "MONDAY", "openTime": "09:00", "closeDay": "MONDAY", "closeTime": "17:00"},
{"openDay": "TUESDAY", "openTime": "09:00", "closeDay": "TUESDAY", "closeTime": "17:00"}
]
}
)# Get location details
curl -X GET "https://zernio.com/api/v1/accounts/YOUR_ACCOUNT_ID/gmb-location-details?readMask=regularHours,specialHours,profile,websiteUri" \
-H "Authorization: Bearer YOUR_API_KEY"
# Update business hours
curl -X PUT https://zernio.com/api/v1/accounts/YOUR_ACCOUNT_ID/gmb-location-details \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"updateMask": "regularHours",
"regularHours": {
"periods": [
{"openDay": "MONDAY", "openTime": "09:00", "closeDay": "MONDAY", "closeTime": "17:00"},
{"openDay": "TUESDAY", "openTime": "09:00", "closeDay": "TUESDAY", "closeTime": "17:00"}
]
}
}'See the GMB Location Details API Reference for the full schema.
Media (Photos)
Upload, list, and delete photos for your Google Business Profile listing. Photo categories: COVER, PROFILE, LOGO, EXTERIOR, INTERIOR, FOOD_AND_DRINK, MENU, PRODUCT, TEAMS, ADDITIONAL.
// List photos
const media = await zernio.googleBusiness.listMedia('YOUR_ACCOUNT_ID');
// Upload a photo
await zernio.googleBusiness.uploadMedia('YOUR_ACCOUNT_ID', {
sourceUrl: 'https://example.com/photos/interior.jpg',
description: 'Dining area with outdoor seating',
category: 'INTERIOR'
});# List photos
media = client.google_business.list_media("YOUR_ACCOUNT_ID")
# Upload a photo
client.google_business.upload_media("YOUR_ACCOUNT_ID",
source_url="https://example.com/photos/interior.jpg",
description="Dining area with outdoor seating",
category="INTERIOR"
)# List photos
curl -X GET https://zernio.com/api/v1/accounts/YOUR_ACCOUNT_ID/gmb-media \
-H "Authorization: Bearer YOUR_API_KEY"
# Upload a photo
curl -X POST https://zernio.com/api/v1/accounts/YOUR_ACCOUNT_ID/gmb-media \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"sourceUrl": "https://example.com/photos/interior.jpg",
"description": "Dining area with outdoor seating",
"category": "INTERIOR"
}'See the GMB Media API Reference for full details.
Attributes
Manage amenities and services like delivery, Wi-Fi, outdoor seating, and payment types. Available attributes vary by business category. Common ones include has_dine_in, has_takeout, has_delivery, has_wifi, has_outdoor_seating, and pay_credit_card_types_accepted.
// Get attributes
const attrs = await zernio.googleBusiness.getAttributes('YOUR_ACCOUNT_ID');
// Update attributes
await zernio.googleBusiness.updateAttributes('YOUR_ACCOUNT_ID', {
attributes: [
{ name: 'has_delivery', values: [true] },
{ name: 'has_outdoor_seating', values: [true] }
],
attributeMask: 'has_delivery,has_outdoor_seating'
});# Get attributes
attrs = client.google_business.get_attributes("YOUR_ACCOUNT_ID")
# Update attributes
client.google_business.update_attributes("YOUR_ACCOUNT_ID",
attributes=[
{"name": "has_delivery", "values": [True]},
{"name": "has_outdoor_seating", "values": [True]}
],
attribute_mask="has_delivery,has_outdoor_seating"
)# Get attributes
curl -X GET https://zernio.com/api/v1/accounts/YOUR_ACCOUNT_ID/gmb-attributes \
-H "Authorization: Bearer YOUR_API_KEY"
# Update attributes
curl -X PUT https://zernio.com/api/v1/accounts/YOUR_ACCOUNT_ID/gmb-attributes \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"attributes": [
{"name": "has_delivery", "values": [true]},
{"name": "has_outdoor_seating", "values": [true]}
],
"attributeMask": "has_delivery,has_outdoor_seating"
}'See the GMB Attributes API Reference for full details.
Place Actions
Manage booking, ordering, and reservation buttons that appear on your listing. Action types: APPOINTMENT, ONLINE_APPOINTMENT, DINING_RESERVATION, FOOD_ORDERING, FOOD_DELIVERY, FOOD_TAKEOUT, SHOP_ONLINE.
// List place actions
const actions = await zernio.googleBusiness.listPlaceActions('YOUR_ACCOUNT_ID');
// Create a place action
await zernio.googleBusiness.createPlaceAction('YOUR_ACCOUNT_ID', {
uri: 'https://order.ubereats.com/mybusiness',
placeActionType: 'FOOD_ORDERING'
});# List place actions
actions = client.google_business.list_place_actions("YOUR_ACCOUNT_ID")
# Create a place action
client.google_business.create_place_action("YOUR_ACCOUNT_ID",
uri="https://order.ubereats.com/mybusiness",
place_action_type="FOOD_ORDERING"
)# List place actions
curl -X GET https://zernio.com/api/v1/accounts/YOUR_ACCOUNT_ID/gmb-place-actions \
-H "Authorization: Bearer YOUR_API_KEY"
# Create a place action
curl -X POST https://zernio.com/api/v1/accounts/YOUR_ACCOUNT_ID/gmb-place-actions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"uri": "https://order.ubereats.com/mybusiness",
"placeActionType": "FOOD_ORDERING"
}'See the GMB Place Actions API Reference for full details.
Services
Get and manage the services offered by a Google Business Profile location. Services can be structured (using a predefined serviceTypeId) or free-form (custom label), with an optional price.
Note: Google's API requires full replacement of the service list. Use
PUT /v1/accounts/{accountId}/gmb-servicesto replace the entire list.
// Get services
const services = await zernio.googleBusiness.getServices('YOUR_ACCOUNT_ID');
console.log('Services:', services);
// Replace services (full replacement)
await zernio.googleBusiness.replaceServices('YOUR_ACCOUNT_ID', {
serviceItems: [
{
freeFormServiceItem: {
category: 'categories/gcid:plumber',
label: {
displayName: 'Pipe Repair',
description: 'Emergency and scheduled pipe repair'
}
},
price: { currencyCode: 'USD', units: '150' }
}
]
});# Get services
services = client.google_business.get_services("YOUR_ACCOUNT_ID")
print("Services:", services)
# Replace services (full replacement)
client.google_business.replace_services("YOUR_ACCOUNT_ID",
service_items=[
{
"freeFormServiceItem": {
"category": "categories/gcid:plumber",
"label": {
"displayName": "Pipe Repair",
"description": "Emergency and scheduled pipe repair"
}
},
"price": {"currencyCode": "USD", "units": "150"}
}
]
)# Get services
curl -X GET https://zernio.com/api/v1/accounts/YOUR_ACCOUNT_ID/gmb-services \
-H "Authorization: Bearer YOUR_API_KEY"
# Replace services (full replacement)
curl -X PUT https://zernio.com/api/v1/accounts/YOUR_ACCOUNT_ID/gmb-services \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"serviceItems": [
{
"freeFormServiceItem": {
"category": "categories/gcid:plumber",
"label": {
"displayName": "Pipe Repair",
"description": "Emergency and scheduled pipe repair"
}
},
"price": {
"currencyCode": "USD",
"units": "150"
}
}
]
}'// List place actions
const actions = await zernio.googleBusiness.listPlaceActions('YOUR_ACCOUNT_ID');
// Create a place action
await zernio.googleBusiness.createPlaceAction('YOUR_ACCOUNT_ID', {
uri: 'https://order.ubereats.com/mybusiness',
placeActionType: 'FOOD_ORDERING'
});# List place actions
actions = client.google_business.list_place_actions("YOUR_ACCOUNT_ID")
# Create a place action
client.google_business.create_place_action("YOUR_ACCOUNT_ID",
uri="https://order.ubereats.com/mybusiness",
place_action_type="FOOD_ORDERING"
)# List place actions
curl -X GET https://zernio.com/api/v1/accounts/YOUR_ACCOUNT_ID/gmb-place-actions \
-H "Authorization: Bearer YOUR_API_KEY"
# Create a place action
curl -X POST https://zernio.com/api/v1/accounts/YOUR_ACCOUNT_ID/gmb-place-actions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"uri": "https://order.ubereats.com/mybusiness",
"placeActionType": "FOOD_ORDERING"
}'See the GMB Place Actions API Reference for full details.
Update an existing place action
Use PATCH /v1/accounts/{accountId}/gmb-place-actions to update an existing action link (change uri and/or placeActionType). Only fields included in the request body are updated.
await zernio.googleBusiness.updatePlaceAction('YOUR_ACCOUNT_ID', {
name: 'locations/123/placeActionLinks/456',
uri: 'https://order.doordash.com/joespizza'
});client.google_business.update_place_action("YOUR_ACCOUNT_ID",
name="locations/123/placeActionLinks/456",
uri="https://order.doordash.com/joespizza"
)curl -X PATCH "https://zernio.com/api/v1/accounts/YOUR_ACCOUNT_ID/gmb-place-actions" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "locations/123/placeActionLinks/456",
"uri": "https://order.doordash.com/joespizza"
}'Analytics
Requires Analytics add-on
Per-post analytics are not available for Google Business Profile. Google deprecated the per-post insights endpoint and did not ship a replacement. Per-post views, clicks and likes for GBP posts no longer exist on Google's side, not on Zernio, not anywhere.
For GBP engagement data, use the location-level Performance API documented below.
Performance Metrics
The Performance API returns daily time-series data for your Google Business Profile location. Metrics include impressions (Maps/Search, desktop/mobile), website clicks, call clicks, direction requests, conversations, bookings, and food orders. Data may be delayed 2-3 days. Max 18 months of historical data.
const { data } = await zernio.analytics.getGoogleBusinessPerformance({
query: {
accountId: 'YOUR_ACCOUNT_ID',
startDate: '2026-01-01',
endDate: '2026-03-31'
}
});
console.log(data.metrics);
// { WEBSITE_CLICKS: { total: 42, values: [...] }, CALL_CLICKS: { total: 7, values: [...] }, ... }response = client.analytics.get_google_business_performance(
account_id='YOUR_ACCOUNT_ID',
start_date='2026-01-01',
end_date='2026-03-31'
)
print(response.metrics)curl "https://zernio.com/api/v1/analytics/googlebusiness/performance?accountId=YOUR_ACCOUNT_ID&startDate=2026-01-01&endDate=2026-03-31" \
-H "Authorization: Bearer YOUR_API_KEY"Available metrics: BUSINESS_IMPRESSIONS_DESKTOP_MAPS, BUSINESS_IMPRESSIONS_DESKTOP_SEARCH, BUSINESS_IMPRESSIONS_MOBILE_MAPS, BUSINESS_IMPRESSIONS_MOBILE_SEARCH, BUSINESS_CONVERSATIONS, BUSINESS_DIRECTION_REQUESTS, CALL_CLICKS, WEBSITE_CLICKS, BUSINESS_BOOKINGS, BUSINESS_FOOD_ORDERS, BUSINESS_FOOD_MENU_CLICKS.
Search Keywords
The Search Keywords API returns keywords that triggered impressions for your location, aggregated monthly. Keywords below a minimum impression threshold set by Google are excluded. Max 18 months of historical data.
const { data } = await zernio.analytics.getGoogleBusinessSearchKeywords({
query: {
accountId: 'YOUR_ACCOUNT_ID',
startMonth: '2026-01',
endMonth: '2026-03'
}
});
data.keywords.forEach(k => console.log(`${k.keyword}: ${k.impressions} impressions`));response = client.analytics.get_google_business_search_keywords(
account_id='YOUR_ACCOUNT_ID',
start_month='2026-01',
end_month='2026-03'
)
for k in response.keywords:
print(f"{k.keyword}: {k.impressions} impressions")curl "https://zernio.com/api/v1/analytics/googlebusiness/search-keywords?accountId=YOUR_ACCOUNT_ID&startMonth=2026-01&endMonth=2026-03" \
-H "Authorization: Bearer YOUR_API_KEY"What You Can't Do
These features are not available through Google Business Profile's API:
- Post videos
- Respond to Q&A (deprecated by Google, replaced by AI-powered "Ask Maps")
- Manage service areas
- Manage business categories
Common Errors
Google Business has a 6.5% failure rate across Zernio's platform (557 failures out of 8,529 attempts). Here are the most frequent errors and how to fix them:
| Error | Meaning | Fix |
|---|---|---|
| "Image not found" | Image URL is inaccessible or requires authentication | Verify URL is publicly accessible. Ensure HTTPS. Test URL in an incognito browser. |
| "Invalid image format" | Unsupported file format or corrupted file | Use JPEG or PNG only. GIF is not supported. Re-export the image if corrupted. |
| "Image too small" | Image dimensions below minimum | Use at least 400 x 300 px. Recommended: 1200 x 900 px. |
| Post not appearing | Post may be pending review or account not verified | Posts may take 24-48 hours to appear. Check Google Business Console for approval status. Ensure account is verified. |
| CTA not working | Invalid or inaccessible URL | Verify URL is valid and accessible. Use HTTPS. Avoid shortened URLs. |
Inbox
Requires Inbox add-on, Build: +$10/mo · Accelerate: +$50/unit · Unlimited: +$1,000/mo
Google Business supports reviews management with real-time notifications.
Reviews
| Feature | Supported |
|---|---|
| List reviews | ✅ |
| Reply to reviews | ✅ |
| Delete reply | ✅ |
| Real-time webhooks | ✅ (review.new, review.updated) |
Limitations
- No DMs - Google Business does not have a messaging system accessible via API
- No comments - Posts on Google Business do not support comments
See Reviews API Reference for endpoint details.
Batch get reviews (multiple locations)
Use POST /v1/accounts/{accountId}/gmb-reviews/batch to fetch reviews across multiple locations in a single request. Reviews are grouped by location in the response.
curl -X POST https://zernio.com/api/v1/accounts/YOUR_ACCOUNT_ID/gmb-reviews/batch \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"locationNames": [
"accounts/123/locations/456",
"accounts/123/locations/789"
],
"pageSize": 50
}'const { data } = await zernio.googleBusiness.batchGetReviews('YOUR_ACCOUNT_ID', {
locationNames: [
'accounts/123/locations/456',
'accounts/123/locations/789'
],
pageSize: 50
});
data.locationReviews.forEach(lr => {
console.log(lr.locationName, lr.totalReviewCount, lr.averageRating);
});data = client.google_business.batch_get_reviews("YOUR_ACCOUNT_ID",
location_names=[
"accounts/123/locations/456",
"accounts/123/locations/789"
],
page_size=50
)
for lr in data["locationReviews"]:
print(lr["locationName"], lr.get("totalReviewCount"), lr.get("averageRating"))Related Endpoints
- Connect Google Business Account - OAuth flow
- Create Post - Post creation and scheduling
- Upload Media - Image uploads
- GMB Reviews - Manage reviews
- GMB Food Menus - Manage food menus
- GMB Location Details - Hours, description, contact info
- GMB Media - Photos management
- GMB Attributes - Amenities and services
- GMB Services - List and replace services
- GMB Place Actions - Booking and ordering links
- Performance Metrics - Daily impressions, clicks, calls, directions, bookings
- Search Keywords - Keywords that triggered impressions
- Reviews