La Google Business Reviews API consente agli sviluppatori di gestire in modo programmatico le recensioni dei clienti su tutte le sedi di Google Business Profile. Che tu stia costruendo una dashboard per la gestione della reputazione, automatizzando le risposte alle recensioni o aggregando feedback da più sedi, questa API fornisce le basi per una gestione scalabile delle recensioni.
Questa guida copre tutto ciò di cui hai bisogno per integrare la GBP API nella tua applicazione: dalla configurazione iniziale all'autenticazione OAuth, dal recupero delle recensioni alla risposta programmatica, fino alla gestione degli inevitabili casi limite che si presentano nei deployment in produzione.

Introduzione alla Google Business Profile API
Le API business di Google si sono evolute significativamente nel corso degli anni. L'implementazione attuale utilizza una combinazione di endpoint API:
- My Business Account Management API (
mybusinessaccountmanagement.googleapis.com/v1): Gestisce account e permessi - My Business Business Information API (
mybusinessbusinessinformation.googleapis.com/v1): Gestisce i dati delle sedi - My Business API v4 (
mybusiness.googleapis.com/v4): Gestisce recensioni e post locali (ancora attiva per queste funzionalità)
La funzionalità Google My Business API reviews risiede specificamente nella API v4. Mentre Google ha migrato molte funzionalità verso i più recenti endpoint v1, la gestione delle recensioni rimane sulla v4 senza alcuna data di deprecazione annunciata.
Nota: Google aggiorna frequentemente la struttura delle proprie API. Gli endpoint v4 per le recensioni sono stabili, ma controlla sempre la documentazione ufficiale per le ultime modifiche.
Cosa Puoi Fare con la Reviews API
La GBP API supporta queste operazioni principali sulle recensioni:
| Operazione | Metodo HTTP | Endpoint |
|---|---|---|
| Elencare recensioni | GET | /accounts/{id}/locations/{id}/reviews |
| Ottenere singola recensione | GET | /accounts/{id}/locations/{id}/reviews/{reviewId} |
| Rispondere a recensione | PUT | /accounts/{id}/locations/{id}/reviews/{reviewId}/reply |
| Aggiornare risposta | PUT | /accounts/{id}/locations/{id}/reviews/{reviewId}/reply |
| Eliminare risposta | DELETE | /accounts/{id}/locations/{id}/reviews/{reviewId}/reply |
Non puoi eliminare le recensioni dei clienti tramite l'API. Solo il recensore o Google (attraverso violazioni delle policy) possono rimuovere le recensioni.
Configurazione del Progetto Google Cloud
Prima di scrivere qualsiasi codice, hai bisogno di un progetto Google Cloud configurato correttamente con le API appropriate abilitate.
Passaggio 1: Creare un Progetto Google Cloud
- Naviga su Google Cloud Console
- Crea un nuovo progetto o selezionane uno esistente
- Annota l'ID del tuo progetto per un uso successivo
Passaggio 2: Abilitare le API Richieste
Abilita queste API nel tuo progetto:
# Usando gcloud CLI
gcloud services enable mybusinessaccountmanagement.googleapis.com
gcloud services enable mybusinessbusinessinformation.googleapis.com
gcloud services enable mybusiness.googleapis.com
Oppure abilitale tramite la Cloud Console:
- My Business Account Management API
- My Business Business Information API
- Google My Business API
Passaggio 3: Configurare la Schermata di Consenso OAuth
- Vai su APIs & Services > OAuth consent screen
- Seleziona il tipo utente External (a meno che tu non abbia un'organizzazione Google Workspace)
- Compila i campi obbligatori:
- Nome app
- Email di supporto utente
- Email di contatto sviluppatore
- Aggiungi lo scope richiesto:
https://www.googleapis.com/auth/business.manage - Aggiungi utenti di test (richiesto mentre sei in modalità test)
Passaggio 4: Creare le Credenziali OAuth
- Vai su APIs & Services > Credentials
- Clicca su Create Credentials > OAuth client ID
- Seleziona Web application
- Aggiungi i tuoi URI di reindirizzamento autorizzati
- Salva il tuo Client ID e Client Secret
// Memorizza questi nelle variabili d'ambiente
const config = {
clientId: process.env.GOOGLE_BUSINESS_CLIENT_ID,
clientSecret: process.env.GOOGLE_BUSINESS_CLIENT_SECRET,
redirectUri: process.env.GOOGLE_BUSINESS_REDIRECT_URI,
};
OAuth 2.0 per Google Business
Google Business Profile richiede OAuth 2.0 con accesso offline per ottenere i refresh token. Questo permette alla tua applicazione di accedere all'API senza richiedere agli utenti di ri-autenticarsi.
Generazione dell'URL di Autorizzazione
function getGoogleBusinessAuthUrl(state?: string): string {
const scopes = [
'https://www.googleapis.com/auth/business.manage',
'https://www.googleapis.com/auth/userinfo.profile',
'https://www.googleapis.com/auth/userinfo.email'
];
const params = new URLSearchParams({
client_id: process.env.GOOGLE_BUSINESS_CLIENT_ID!,
redirect_uri: process.env.GOOGLE_BUSINESS_REDIRECT_URI!,
scope: scopes.join(' '),
response_type: 'code',
access_type: 'offline',
prompt: 'consent', // Forza la schermata di consenso per garantire il refresh token
});
if (state) {
params.append('state', state);
}
return `https://accounts.google.com/o/oauth2/auth?${params.toString()}`;
}
Il parametro prompt: 'consent' è fondamentale. Senza di esso, Google potrebbe non restituire un refresh token nelle autorizzazioni successive.
Scambio del Codice di Autorizzazione
Dopo che l'utente autorizza la tua applicazione, Google lo reindirizza con un codice di autorizzazione:
interface TokenResponse {
access_token: string;
refresh_token?: string;
expires_in: number;
token_type: string;
scope: string;
}
async function exchangeCodeForToken(code: string): Promise<TokenResponse> {
const response = await fetch('https://oauth2.googleapis.com/token', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({
code,
client_id: process.env.GOOGLE_BUSINESS_CLIENT_ID!,
client_secret: process.env.GOOGLE_BUSINESS_CLIENT_SECRET!,
redirect_uri: process.env.GOOGLE_BUSINESS_REDIRECT_URI!,
grant_type: 'authorization_code',
}),
});
if (!response.ok) {
const errorText = await response.text();
throw new Error(`Scambio token fallito: ${response.status} ${errorText}`);
}
return response.json();
}
Nota: Memorizza il refresh token in modo sicuro. Viene restituito solo durante l'autorizzazione iniziale (o quando si usa
prompt: 'consent').
Struttura di Account e Sedi
La GBP API utilizza una struttura gerarchica: gli Utenti hanno Account, e gli Account contengono Sedi. Hai bisogno di entrambi gli ID per accedere alle recensioni.
Recupero degli Account Utente
interface GBPAccount {
name: string; // Formato: "accounts/123456789"
accountName: string;
type: string;
role: string;
state: { status: string };
}
async function getAccounts(accessToken: string): Promise<GBPAccount[]> {
const allAccounts: GBPAccount[] = [];
let pageToken: string | undefined;
do {
const url = new URL('https://mybusinessaccountmanagement.googleapis.com/v1/accounts');
url.searchParams.set('pageSize', '100');
if (pageToken) {
url.searchParams.set('pageToken', pageToken);
}
const response = await fetch(url.toString(), {
headers: { Authorization: `Bearer ${accessToken}` },
});
if (!response.ok) {
throw new Error(`Recupero account fallito: ${response.status}`);
}
const data = await response.json();
if (data.accounts) {
allAccounts.push(...data.accounts);
}
pageToken = data.nextPageToken;
} while (pageToken);
return allAccounts;
}
Recupero delle Sedi per un Account
interface GBPLocation {
name: string; // Formato: "locations/987654321"
title: string;
storefrontAddress?: {
addressLines: string[];
locality: string;
administrativeArea: string;
postalCode: string;
regionCode: string;
};
websiteUri?: string;
}
async function getLocations(
accessToken: string,
accountId: string
): Promise<GBPLocation[]> {
const allLocations: GBPLocation[] = [];
let pageToken: string | undefined;
do {
const url = new URL(
`https://mybusinessbusinessinformation.googleapis.com/v1/${accountId}/locations`
);
url.searchParams.set('readMask', 'name,title,storefrontAddress,websiteUri');
url.searchParams.set('pageSize', '100');
if (pageToken) {
url.searchParams.set('pageToken', pageToken);
}
const response = await fetch(url.toString(), {
headers: { Authorization: `Bearer ${accessToken}` },
});
if (!response.ok) {
throw new Error(`Recupero sedi fallito: ${response.status}`);
}
const data = await response.json();
if (data.locations) {
allLocations.push(...data.locations);
}
pageToken = data.nextPageToken;
} while (pageToken);
return allLocations;
}
Recupero delle Recensioni con la Google Business Reviews API
Con gli ID di account e sede a disposizione, puoi recuperare le recensioni. La Google Business Reviews API restituisce le recensioni in ordine cronologico inverso per impostazione predefinita.
Recupero Base delle Recensioni
interface ReviewReply {
comment: string;
updateTime: string;
}
interface Review {
id: string;
name: string;
reviewer: {
displayName: string;
profilePhotoUrl?: string;
isAnonymous: boolean;
};
rating: number;
starRating: 'ONE' | 'TWO' | 'THREE' | 'FOUR' | 'FIVE';
comment?: string;
createTime: string;
updateTime: string;
reviewReply?: ReviewReply;
}
interface ReviewsResponse {
reviews: Review[];
averageRating?: number;
totalReviewCount?: number;
nextPageToken?: string;
}
async function getReviews(
accessToken: string,
accountId: string,
locationId: string,
options?: { pageSize?: number; pageToken?: string }
): Promise<ReviewsResponse> {
// Estrai gli ID numerici se vengono forniti i nomi completi delle risorse
const accId = accountId.includes('/') ? accountId.split('/').pop() : accountId;
const locId = locationId.includes('/') ? locationId.split('/').pop() : locationId;
const pageSize = Math.min(options?.pageSize || 50, 50); // Max 50 per richiesta
const url = new URL(
`https://mybusiness.googleapis.com/v4/accounts/${accId}/locations/${locId}/reviews`
);
url.searchParams.set('pageSize', String(pageSize));
if (options?.pageToken) {
url.searchParams.set('pageToken', options.pageToken);
}
const response = await fetch(url.toString(), {
headers: { Authorization: `Bearer ${accessToken}` },
});
if (!response.ok) {
const errorBody = await response.text();
throw new Error(`Recupero recensioni fallito: ${response.status} ${errorBody}`);
}
const data = await response.json();
// Mappa le stringhe di valutazione a stelle in valori numerici
const starRatingMap: Record<string, number> = {
ONE: 1,
TWO: 2,
THREE: 3,
FOUR: 4,
FIVE: 5,
};
const reviews = (data.reviews || []).map((review: any) => ({
id: review.reviewId || review.name?.split('/').pop(),
name: review.name,
reviewer: {
displayName: review.reviewer?.displayName || 'Anonimo',
profilePhotoUrl: review.reviewer?.profilePhotoUrl || null,
isAnonymous: review.reviewer?.isAnonymous || false,
},
rating: starRatingMap[review.starRating] || 0,
starRating: review.starRating,
comment: review.comment || '',
createTime: review.createTime,
updateTime: review.updateTime,
reviewReply: review.reviewReply
? {
comment: review.reviewReply.comment,
updateTime: review.reviewReply.updateTime,
}
: null,
}));
return {
reviews,
averageRating: data.averageRating,
totalReviewCount: data.totalReviewCount,
nextPageToken: data.nextPageToken,
};
}
Recupero di Tutte le Recensioni con Paginazione
Per le sedi con molte recensioni, dovrai gestire la paginazione:
async function getAllReviews(
accessToken: string,
accountId: string,
locationId: string
): Promise<Review[]> {
const allReviews: Review[] = [];
let pageToken: string | undefined;
do {
const response = await getReviews(accessToken, accountId, locationId, {
pageSize: 50,
pageToken,
});
allReviews.push(...response.reviews);
pageToken = response.nextPageToken;
// Aggiungi un piccolo ritardo per evitare il rate limiting
if (pageToken) {
await new Promise((resolve) => setTimeout(resolve, 100));
}
} while (pageToken);
return allReviews;
}
Rispondere alle Recensioni in Modo Programmatico
La possibilità di rispondere alle recensioni Google tramite API in modo programmatico è essenziale per le aziende che gestiscono più sedi. Risposte tempestive alle recensioni migliorano la percezione del cliente e possono avere un impatto positivo sulla SEO locale.
Creazione di una Risposta alla Recensione
async function replyToReview(
accessToken: string,
reviewName: string,
replyText: string
): Promise<{ success: boolean }> {
// formato reviewName: accounts/{accountId}/locations/{locationId}/reviews/{reviewId}
const response = await fetch(
`https://mybusiness.googleapis.com/v4/${reviewName}/reply`,
{
method: 'PUT',
headers: {
Authorization: `Bearer ${accessToken}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
comment: replyText,
}),
}
);
if (!response.ok) {
const errorBody = await response.text();
throw new Error(`Risposta alla recensione fallita: ${response.status} ${errorBody}`);
}
return { success: true };
}