L'API Google My Business offre pléthore de fonctionnalités intéressantes pour les webmasters. Que vous souhaitiez simplement obtenir des informations relatives aux adresses locales, que vous vouliez ajouter des photos ou que vous désiriez poster des publications de façon automatisée, l'API répond à toutes vos requêtes. Terminons donc au travers de cet article notre tour d'horizon des atouts de Google My Business, si chers au référencement local…

Par Mathieu Chartier

La lettre d'Abondance de septembre 2018 a introduit l'API Google My Business, il est donc recommandé aux lecteurs de le relire pour ne pas être totalement perdu à la lecture de la suite et fin de cette aventure dans le SEO local par le code. Rappelons toutefois que cette API n'est pas libre d'accès comme la plupart des programmes de Google, il convient de remplir un formulaire d'inscription pour obtenir un accès aux fonctionnalités décrites par la suite (source : http://bit.ly/2ozwkN5).

Après avoir déjà fait le tour de l'obtention d'informations générales ou de modifications d'une fiche Google My Business, découvrons maintenant comment l'API peut nous permettre de mener d'autres actions intéressantes pour le SEO local…

Administrer des publications

Une des fonctionnalités les plus intéressantes de Google My Business est certainement la possibilité de publier des actualités, offres et événements dans la section locale visible dans les SERP de Google. Les publications permettent d'occuper davantage d'espace visuel mais aussi de mettre en avant des informations concernant un business local.

Comme pour toutes les API REST, celle de Google My Business permet toujours d'effectuer les actions courantes : GET (obtenir des informations ou lister des données), POST (publier), DELETE (supprimer), PATCH/UPDATE (mettre à jour). C'est encore une fois le cas pour la gestion des publications, il est donc possible d'effectuer toutes les actions désirées.

Commençons tout d'abord par lister l'ensemble des publications existantes d'un compte. Cela permet de récupérer toutes les informations utiles, comme leur type, leur titre, leur image relative ou encore les liens des boutons call-to-action mis en place. Si vous souhaitez modifier ou supprimer ultérieurement des publications, il faudra aussi leur « name » complet. C'est pourquoi le code suivant le retourne dans la première colonne du tableau (voir figure 1). Nous utiliserons la méthode listAccountsLocationsLocalPosts() de la Google PHP API Client pour mener à bien notre revue des publications.

 

Rappelons qu'il faut repartir de ce qui est indiqué dans la lettre d'Abondance du mois précédent, mais pour ceux qui auraient manqué cela, voici le code complet, avec la connexion à l'API (ce morceau de code sera retiré par la suite mais devra toujours être présent) :

 

/*==================================================*/
/*=== API Client et authentification obligatoire ===*/
/*==================================================*/
// Source intéressante : https://pastebin.com/jA9sBNTk

// Autoload des classes PHP pour utiliser les API de Google
require_once('google-api-php-client-2.2.2/vendor/autoload.php');

// Création d'une connexion aux API
$client = new Google_Client();

// Rédirection pour la connexion OAuth
$client->setAuthConfig('client_secret_xxx.json'); // À adapter à notre compte !
$redirect_uri = "http://".$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'];
$client->setRedirectUri($redirect_uri);

// Ajout de la portée du service (autorisation -> scope) => URL Search Console
$client->setIncludeGrantedScopes(true);
$client->addScope("https://www.googleapis.com/auth/plus.business.manage");

// Accès hors-ligne autorisé et approbation forcée (optionnel)
$client->setAccessType("offline");
$client->setApprovalPrompt("force");

// Ajouter un Guzzle (pour cURL en PHP)
$http = new GuzzleHttpClient(['verify' => false]);
$client->setHttpClient($http);
$client->authorize($http);

// Validation de l'authentification (redirection pour se connecter et obtenir un token valide)
session_start();
if(!isset($_GET['code'])) {
            // Génère une URL pour autoriser l'utilisateur OAuth 2
            $authUrl = $client->createAuthUrl();
            header('Location:'.filter_var($authUrl, FILTER_SANITIZE_URL));
            return;
} else {
            if(isset($_SESSION['token'])) {
                       $client->setAccessToken($_SESSION['token']);
                       if($client->isAccessTokenExpired()) {
                                   $client->refreshToken($_SESSION['token']['refresh_token']);
                       }
            } else {
                       $client->authenticate($_GET['code']);
                       $_SESSION['token'] = $client->getAccessToken();
            }
}

/*==========================================*/
/*=== Utilisation des fonctions de l'API ===*/
/*==========================================*/
// Appel de la méthode de connexion à l'API Google My Business
$api_mb = new Google_Service_MyBusiness($client);

// Jouer avec les publications locales (posts)
$mb_accounts_posts = $api_mb->accounts_locations_localPosts;

// 1. Liste des publications déjà publiées
$location_name = "accounts/ID_COMPTE/locations/ID_LOCATION"; // Business
$list_accounts_locations_posts = $mb_accounts_posts->listAccountsLocationsLocalPosts($account_name);
            $affichage = "<table>";
            $affichage.= "<tr>";
            $affichage.= "<th>Local Post Name</th>";
            $affichage.= "<th>Date de publication</th>";
            $affichage.= "<th>Type de publication</th>";
            $affichage.= "<th>Titre de la publication</th>";
            $affichage.= "<th>Description</th>";
            $affichage.= "<th>Informations</th>";
            $affichage.= "<th>Call-to-action (optionnel)</th>";
            $affichage.= "<th>Photo (optionnelle)</th>";
            $affichage.= "</tr>";

            foreach($list_accounts_locations_posts as $post) {
                       // Récupération du "titre"
                       if($post['topicType'] == "EVENT") {
                                   $titre = $post['event']['title'];
                       } elseif($post['topicType'] == "PRODUCT") {
                                   $titre = $post['product']['productName'];
                       } else {
                                   $titre = "Lien direct";
                       }

                       // Récupération des infos selon le type de données
                       $infos = "";
                       if($post['topicType'] == "EVENT") {
                                   $infos.= "Date : ";
                                   $infos.= $post['event']['schedule']['startDate']['day']."/";
                                   $infos.= $post['event']['schedule']['startDate']['month']."/";
                                   $infos.= $post['event']['schedule']['startDate']['year'];
                                   if(!empty($post['event']['schedule']['startTime']['hours'])) {
                                               $infos.= " - ".$post['event']['schedule']['startTime']['hours']."h";
                                               $infos.= $post['event']['schedule']['startTime']['minutes']."min";
                                   }
                                   $infos.= " au ";
                                   $infos.= $post['event']['schedule']['endDate']['day']."/";
                                   $infos.= $post['event']['schedule']['endDate']['month']."/";
                                   $infos.= $post['event']['schedule']['endDate']['year'];
                                   if(!empty($post['event']['schedule']['endTime']['hours'])) {
                                               $infos.= " - ".$post['event']['schedule']['endTime']['hours']."h";
                                               $infos.= $post['event']['schedule']['endTime']['minutes']."min";
                                   }
                       } elseif($post['topicType'] == "PRODUCT") {
                                   $infos.= "Tarif : ";
                                   $infos.= $post['product']['upperPrice']['units']." ";
                                   $infos.= $post['product']['upperPrice']['currencyCode'];
                       }

                       // Call-to-Action (optionnel)
                       $callToAction = "";
                       if(isset($post['callToAction'])) {
                                   $callToAction.= '<a href="'.$post['callToAction']['url'].'">Bouton de type "'.$post['callToAction']['actionType'].'"</a>';
                       }

                       // Récupération de la photo (si existante)
                       $photo = "";
                       if(!empty($post['media'])) {
                                   foreach($post['media'] as $media) {
                                               if($media['mediaFormat'] == "PHOTO") {
                                                          $photo.= '<img src="'.$media['googleUrl'].'" alt="Google My Business Media"/>';
                                               }
                                   }
                       }

                       $affichage.= "<tr>";
                       $affichage.= "<td>".$post['name']."</td>";
                       $affichage.= "<td>".date('d/m/Y à h:i:s', strtotime($post['createTime']))."</td>";
                       $affichage.= "<td>".$post['topicType']."</td>";
                       $affichage.= "<td><a href='".$post['searchUrl']."' target='_blank'>".$titre."</a></td>";
                       $affichage.= "<td>".$post['summary']."</td>";
                       $affichage.= "<td>".$infos."</td>";
                       $affichage.= "<td>".$callToAction."</td>";
                       $affichage.= "<td>".$photo."</td>";
                       $affichage.= "</tr>";
            }
            $affichage.= "</table>";
            print $affichage;

 

Ce code permet d'afficher la plupart des données importantes pour les publications de type « événement », « produit » ou « standard ». Il faudrait reproduire ce genre de programme pour tous les types de données pour être totalement complet.


Fig. 1. Liste des informations relatives à des publications dans Google My Business.

La création ou l'édition de publications passe par les méthodes create() ou patch() contenant au moins deux arguments. Tout d'abord le « name » du compte et de l'adresse souhaitant publier, et ensuite un objet de type Google_Service_MyBusiness_LocalPost qui permet de préciser les informations à afficher dans la publication. Cela consiste donc à composer son type de publication avec les informations nécessaires.

Dans notre exemple, nous créons une publication standard (voir figure 2 pour l'affichage après création) avec une image et un call-to-action. Vous pourrez partir de cet exemple pour concevoir d'autres types de publications, avec la même logique de création.

 

// 2. Créer une publication
// accounts/ID_compte/locations/ID_location
$location_name = "accounts/ID_COMPTE/locations/ID_LOCATION"; // Business

// Liste des données
$postBody = new Google_Service_MyBusiness_LocalPost();
$postBody->setCreateTime("2018-09-25T16:33:10.768Z");
$postBody->setTopicType("STANDARD");
$postBody->setState("LIVE");
$postBody->setSummary("Exemple de description pour une nouvelle publication dans Google My Business, créée avec l'API de Google.");
$postBody->setLanguageCode("fr");
$call2action = new Google_Service_MyBusiness_CallToAction();
$call2action->setActionType("LEARN_MORE");
$call2action->setUrl("https://developers.google.com/my-business/");
$postBody->setCallToAction($call2action);
$media = new Google_Service_MyBusiness_MediaItem();
$media->setSourceUrl("https://image.slidesharecdn.com/gmbapi-151102190207-lva1-app6892/95/gmb-api-google-my-business-1-638.jpg?cb=1446491033");
$media->setMediaFormat("PHOTO");
$postBody->setMedia($media);

// Création de la publication
$create_accounts_locations_posts = $mb_accounts_posts->create($account_name, $postBody);

 

Une fois ce code appliqué, vous pouvez donc retrouver directement la publication dans les SERP de Google, comme le montre la figure suivante. Sachez que l'édition d'une publication se ferait sur le même principe, sauf que la méthode utilisée en fin de code serait patch() au lieu de create().


Fig. 2. Exemple de publication créée via l'API Google My Business.

Maintenant que nous savons créer ou éditer des publications, il peut être intéressant de savoir en supprimer afin de nettoyer la liste (en cas d'erreur de création notamment). Pour ce faire, il faut absolument connaître l'identifiant (ID) de la publication ciblée. Le plus simple est souvent de réutiliser la technique de listage vue en début d'article pour obtenir ceci. Dans notre exemple suivant, nous supprimons la publication créée pour la figure 2, en seulement quelques lignes de code, à l'aide de la méthode delete() :

// 3. Supprimer une publication
// accounts/ID_compte/locations/ID_location/localPosts/ID_post
$account_name = "accounts/100359724469727920312/locations/14388344723556769785/localPosts/8725176796367510675";
$create_accounts_locations_posts = $mb_accounts_posts->delete($account_name);

 

Rien de plus simple, n'est-ce-pas ? Vous savez désormais comment appliquer toutes les méthodes utiles pour la gestion des publications. Ce n'est pas pour autant que notre tour d'horizon de l'API Google My Business se termine... Nous allons maintenant voir comment gérer les notes ou obtenir des statistiques intéressantes relatives à nos actions en SEO local…

Administrer et recueillir les notes des utilisateurs

Un des points forts de Google My Business est de pouvoir être noté par des utilisateurs extérieurs. Certes, nous savons que les avis peuvent parfois manquer d'objectivité, mais comme tous les business locaux sont logés à la même enseigne, nous pouvons estimer que cela est plutôt révélateur d'une tendance vers la vérité.

L'API permet de lister tous les commentaires, mais aussi d'obtenir des informations sur un avis en particulier. Il est également possible de poster une réponse automatiquement ou de supprimer une réponse. Bien entendu, la neutralité de Google My Business impose à l'outil l'impossibilité de supprimer des avis, que ce soit dans l'interface classique ou via l'API. C'est une bonne chose qui permet d'éviter la suppression systématique de tous les avis négatifs, par exemple…

Il faut passer par la méthode accounts_locations_reviews de l'API PHP pour accéder aux méthodes intéressantes. Nous débuterons comme toujours par le listing des avis, ici avec la méthode listAccountsLocationsReviews(). Le code suivant montre comment récupérer toutes les données des avis dans un tableau, à savoir le nom du commentateur, sa note, son commentaire, sa date de publication et le « name » du commentaire (utile pour le webmaster car il contient l'identifiant de l'avis en cas de besoin pour publier une réponse par exemple). Enfin, si une réponse à un avis existe, celle-ci s'affiche avec la date de réponse.

// 1. Lister tous les commentaires : https://developers.google.com/my-business/content/review-data
$location_name = "accounts/ID_COMPTE/locations/ID_LOCATION"; // Business
$reviews = $mb_accounts_reviews->listAccountsLocationsReviews($account_name);
            $affichage = "<table>";
            $affichage.= "<tr>";
            $affichage.= "<th>Review Name</th>";
            $affichage.= "<th>Date de création</th>";
            $affichage.= "<th>Note sur 5</th>";
            $affichage.= "<th>Commentateur</th>";
            $affichage.= "<th>Commentaire</th>";
            $affichage.= "<th>Réponse (optionnelle)</th>";
            $affichage.= "<th>Date de la réponse</th>";
            $affichage.= "</tr>";

            foreach($reviews['reviews'] as $review) {
                       $affichage.= "<tr>";
                       $affichage.= "<td>".$review['name']."</td>";
                        $affichage.= "<td>".date('d/m/Y à h:i:s', strtotime($review['createTime']))."</td>";
                       $affichage.= "<td>".$review['starRating']."</td>";
                       $affichage.= "<td>".$review['reviewer']['displayName']."</td>";
                       $affichage.= "<td>".$review['comment']."</td>";
                       if(isset($review['reviewReply'])) {
                                   $affichage.= "<td>".$review['reviewReply']['comment']."</td>";
                                   $affichage.= "<td>".date('d/m/Y à h:i:s', strtotime($review['reviewReply']['updateTime']))."</td>";
                       }
                       $affichage.= "</tr>";
            }

            $affichage.= "</table>";
            echo $affichage;

 

La méthode updateReply() permet de mettre à jour une réponse ou d'en créer une (si elle n'existe pas pour l'avis ciblé). Elle demande en premier paramètre le « name » de l'avis, et en second paramètre un objet de type Google_Service_MyBusiness_ReviewReply, contenant le corps de la réponse.

C'est extrêmement simple à créer car l'API ne demande que le texte de la réponse et la date de création (au format ISO). Il ne faut donc que quelques lignes pour automatiser des réponses. Nous n'irons pas dans les détails de ce qu'il est possible de créer mais vous pourriez par exemple imaginer une gestion avec une liste de réponses types selon la notation donnée (mais il reste toujours recommandé de faire cette gestion manuellement pour vraiment fidéliser et répondre aux attentes des usagers). Le code suivant créé une réponse simple, que vous pourrez retrouver dans la figure 3.

// 2. Créer/Éditer une réponse à un avis existant
// Schéma : accounts/ID_compte/locations/ID_location/reviews/ID_review
$review_name = "accounts/ID_COMPTE/locations/ID_LOCATION/reviews/ID_REVIEW"; // Note

// Liste des données
$postBody = new Google_Service_MyBusiness_ReviewReply();
$date = date("c"); // Date au format ISO
$postBody->setUpdateTime($date);
$postBody->setComment("Merci pour votre avis positif. Nous espérons continuer de faire le meilleur travail possible !");

// Création/Édition de la réponse à un commentaire/avis
$mb_accounts_reviews->updateReply($review_name, $postBody);


Fig. 3. Réponse du propriétaire créée via l'API Google My Business.

Enfin, bouclons la boucle en découvrant comment supprimer une réponse. C'est encore plus simple car il convient juste d'utiliser la méthode deleteReply() avec le « name » de l'avis en paramètre, comme ceci :

// 3. Suppression d'une réponse à un avis
// Schéma : accounts/ID_compte/locations/ID_location/reviews/ID_review
$review_reply_name = "accounts/100359724469727920312/locations/14388344723556769785/reviews/AIe9_BFqh_zr355jzGaEpH7666zc5zlPg-R0lO9jKP2yeHQcWaDByEhYTayqb1L1kOBwXEVjwpExWaCVKSBx0au4gPHmhQEszAEXBVQu21ZsoefViEepmHU"; // Exemple
$mb_accounts_reviews->deleteReply($review_reply_name);

 

Comme la gestion des commentaires n'a plus de secrets pour vous, clôturons notre utilisation de l'API Google My Business en obtenant quelques statistiques. Ce sera relativement succinct, car l'outil ne dresse pas des listes de données chiffrées comme Google Analytics, mais cela peut toujours être utile pour créer ses propres tableaux de bord ou pour croiser des données.

Obtenir des statistiques de Google My Business

Tout d'abord, concentrons-nous sur les statistiques globales d'un business, comme le nombre de recherches directes ou indirectes, le nombre de clics via Google Maps, etc. Nous résumerons ces données juste après, afin que vous ne soyez pas perdus.

Pour obtenir ces données avec l'API, il convient de faire appel à l'objet accounts_locations. Ce dernier possède une méthode reportInsights() qui permet de récupérer les informations statistiques (ce n'est pas le seul objet dans l'API à posséder une telle méthode, il ne faut pas se tromper…). Plutôt que de faire de longs discours, voici la section du code qui permet d'afficher les résultats globaux :
 

// Obtenir des statistiques : https://developers.google.com/my-business/content/insight-data
$mb_accounts_stats = $api_mb->accounts_locations;

// 1. Récupérer les "basic insights"
$account_name = "accounts/ID_COMPTE"; // Compte général
$location_name = "accounts/ID_COMPTE/locations/ID_LOCATION"; // Business

// Paramétrage
$basic = new Google_Service_MyBusiness_ReportLocationInsightsRequest();
$basic_metrics = new Google_Service_MyBusiness_BasicMetricsRequest();
$basic_metric_request = new Google_Service_MyBusiness_MetricRequest();
$basic_metric_request->setMetric('ALL');
// $basic_metric_request->setOptions("AGGREGATED_DAILY"); // Pour obtenir des statistiques à la journée
$basic_metrics->setMetricRequests($basic_metric_request);
$basic_metrics_times = new Google_Service_MyBusiness_TimeRange();
$basic_metrics_time_start = $basic_metrics_times->setStartTime(date('c', strtotime('2018-09-01'))); // Date au format ISO
$basic_metrics_time_end = $basic_metrics_times->setEndTime(date('c')); // Date au format ISO
$basic_metrics->setTimeRange($basic_metrics_times);
$basic->setBasicRequest($basic_metrics);
$basic->setLocationNames(array($location_name));

// Requête finale avec la méthode reportInsights()
$basicInsights = $mb_accounts_stats->reportInsights($account_name, $basic);

 

La variable $basicInsights en fin de code contient la totalité des informations. Sachez que vous pouvez opter pour l'affichage des chiffres généraux (selon l'intervalle de temps défini dans le code), ou pour les données statistiques jour par jour. Dans ce second cas, vous devrez décommenter la ligne contenant « AGGREGATED_DAILY » dans le code précédent.

Ensuite, le code suivant devrait vous permettre d'obtenir un affichage des données dans un tableau, avec les informations brutes provenant de l'API. Ce code peut évidemment être totalement personnalisé selon ce que vous souhaitez obtenir comme résultat final.

foreach($basicInsights['locationMetrics'] as $locationMetric) {
            $affichage = "<table>";
            $affichage.= "<tr>";
            $affichage.= '<th colspan="5">Compte : '.$locationMetric['locationName'].' ('.$locationMetric['timeZone'].')</th>';
            $affichage.= "</tr>";
            $affichage.= "<tr>";
            $affichage.= "<th>Type de métrique</th>";
            $affichage.= "<th>Option choisie</th>";
            $affichage.= "<th>Valeur</th>";
            $affichage.= "<th>Intervalle de départ</th>";
            $affichage.= "<th>Intervalle de fin</th>";
            $affichage.= "</tr>";
            foreach($locationMetric['metricValues'] as $metric) {
                       if($metric['totalValue']['metricOption'] == "AGGREGATED_TOTAL") {
                                   $affichage.= "<tr>";
                                   $affichage.= "<td>".$metric['metric']."</td>";
                                   $affichage.= "<td>".$metric['totalValue']['metricOption']."</td>";
                                   $affichage.= "<td>".$metric['totalValue']['value']."</td>";
                                   $affichage.= "<td>".date('d/m/Y à h:i:s', strtotime($metric['totalValue']['timeDimension']['timeRange']['startTime']))."</td>";
                                   $affichage.= "<td>".date('d/m/Y à h:i:s', strtotime($metric['totalValue']['timeDimension']['timeRange']['endTime']))."</td>";
                                   $affichage.= "</tr>";
                       } else {
                                   foreach($metric['dimensionalValues'] as $subMetric) {
                                               $affichage.= "<tr>";
                                               $affichage.= "<td>".$metric['metric']."</td>";
                                               $affichage.= "<td>".$subMetric['metricOption']."</td>";
                                               $affichage.= "<td>".$subMetric['value']."</td>";
                                               $affichage.= "<td>".date('d/m/Y à h:i:s', strtotime($subMetric['timeDimension']['timeRange']['startTime']))."</td>";
                                               $affichage.= "<td></td>";
                                               $affichage.= "</tr>";
                                   }
                       }
            }
            $affichage.= "</table>";
}
echo $affichage;

 

La figure 4 montre le résultat de ce code complet pour des résultats globaux sur une durée d'un mois environ (en général, les données des trois derniers jours ne sont pas accessibles, et donc décomptées du total).


Fig. 4. Tableau des statistiques générales de Google My Business.

L'API Google My Business reprend de nombreuses statistiques avec reportInshigts() mais il est important de faire le parallèle avec ce que vous pourriez retrouver dans l'interface classique. Voici donc une sorte de tableau de correspondance (source : http://bit.ly/2IvkVqt) :

 


Fig. 5. Tableau de correspondance des variables de statistiques.

Vous savez désormais comment obtenir toutes ces informations avec l'API Google My Business en PHP. Retenez toutefois qu'il n'est possible d'effectuer des appels que pour 10 entreprises locales seulement, les données seront masquées au-delà de cette limite.

Le grand manque de l'API reste de pouvoir récupérer la liste des requêtes tapées par les internautes et mobinautes qui ont permis d'afficher la fiche d'une entreprise locale dans la recherche Google ou dans Google Maps. À l'instar de l'API Search Console qui ne permet pas d'obtenir la liste des requêtes tapées, l'API Google My Business nous laisse orphelin de ces données majeures. Il semblerait que ce choix délibéré de Google ne soit pas innocent, mais espérons que l'avenir sera plus clément à ce sujet…

Et si l'API nous réservait encore des surprises ?

L'API Google My Business est remplie à ras-bord de fonctionnalités et nous n'avons pas pu faire le tour de toutes les possibilités (comme celles de gérer les administrateurs d'un compte, de vérifier une adresse ajoutée ou d'ajouter des photos à la volée), malgré le découpage de notre article en deux parties. Nous espérons toutefois que ces premières impressions vous donneront envie d'en découvrir davantage par vous-même et de profiter des bienfaits des fonctionnalités présentées. Certaines fonctions sont assez simples à intégrer et peuvent vraiment se révéler intéressantes pour automatiser des tâches ou croiser des données statistiques avez d'autres outils, n'hésitez pas à les utiliser à bon escient…


Mathieu Chartier
Consultant-Formateur et webmaster indépendant, Internet-Formation (https://www.internet-formation.fr)