Conecte o Google Business Profile e importe seus locais

Crie um link de conexão do Google, associe as listagens do Google do proprietário aos seus locais, confirme e importe as que ainda não têm local.

Uma conta Google conectada permite publicar e gerar relatórios para um local no Google. Até que uma conta seja conectada, a linha do Google Maps nas listagens premium de um local permanece REQUIRING_ACTION, as avaliações do Google não são importadas, as postagens não podem ser publicadas em GOOGLE e os dados de análise do Google retornam null. Conectar a conta resolve os quatro problemas.

O fluxo em lote (etapas 1 a 6) conecta uma conta Google inteira uma única vez e associa cada listagem pertencente a ela aos seus locais. O fluxo para um único local (etapa 7) conecta um local por vez: o link está vinculado àquele local, portanto não há uma etapa de associação depois.

O link tem como escopo a conta à qual pertence a chave de API, portanto o corpo contém apenas suas duas URLs de redirecionamento. Encaminhe o proprietário para o url retornado; o Google o redireciona para successUrl ou errorUrl quando ele conclui o processo.

Connect link
curl -X POST https://listingsapi.com/api/v4/connected-accounts/connect-google \-H "Authorization: API $LISTINGSAPI_KEY" \-H "Content-Type: application/json" \-d '{  "input": {    "successUrl": "https://app.example.com/connect/google/success",    "errorUrl": "https://app.example.com/connect/google/error"  }}'
JSON
{  "data": {    "bulkConnectLinkForGoogle": {      "success": true,      "url": "https://connect.example.com/oauth?token=8f3c1d92-...",      "errors": null    }  }}

O url acima é um valor de exemplo. Encaminhe o proprietário para o url retornado na sua própria resposta.

O link é válido por 24 horas. Verifique se url não é nulo em vez de confiar apenas em success. Se as credenciais do proprietário expirarem posteriormente, crie um novo link da mesma forma: a conexão existente é renovada, não duplicada.

2. Liste as contas conectadas após o retorno do OAuth

Quando o proprietário chegar ao seu successUrl, liste as contas Google. Esta é uma página com paginação por deslocamento: records[] mais pageInfo.totalRecords, paginada com page e perPage.

List accounts
curl "https://listingsapi.com/api/v4/connected-accounts?publisher=GoogleAccount&page=1&perPage=20" \-H "Authorization: API $LISTINGSAPI_KEY"
JSON
{  "data": {    "connectedAccountsInfo": {      "pageInfo": { "hasNextPage": false, "totalRecords": 1 },      "records": [        {          "connectedAccountId": "4f712c17-4f95-42dd-90f4-97171a2e67b5",          "email": "owner@brightsmile-dental.com",          "status": "CONNECTED",          "requestMatchesStatus": "MATCH_COMPLETED",          "connectedLocationsCount": 0        }      ]    }  }}

Selecione o registro cujo email corresponde ao proprietário que acabou de dar consentimento e guarde seu connectedAccountId. Todas as chamadas posteriores recebem esse UUID.

statusSignificado
CONNECTEDAs credenciais são válidas. É seguro iniciar a associação.
MATCH_IN_PROGRESSUm processo de associação está na fila ou em execução.
CONNECTIVITY_ISSUEA autorização expirou. connectivityIssue informa o motivo; gere novamente o link de conexão.

O filtro de consulta opcional status usa palavras diferentes (Connected, NotConnected, ConnectionIssue); passar o próprio status de um registro como valor do filtro retorna um 400.

3. Inicie a associação

O processo de associação busca todos os perfis que a conta pode acessar e associa cada um a um dos seus locais. Ele apenas gera sugestões; nada é vinculado ainda.

Trigger matches
curl -X POST https://listingsapi.com/api/v4/connected-accounts/trigger-matches \-H "Authorization: API $LISTINGSAPI_KEY" \-H "Content-Type: application/json" \-d '{ "input": { "connectedAccountIds": ["4f712c17-4f95-42dd-90f4-97171a2e67b5"] } }'

A resposta é data.connectedAccountsTriggerMatches com success e failedIds. success: true significa que a tarefa foi colocada na fila; qualquer conta que não pôde ser colocada na fila é listada em failedIds.

4. Consulte periodicamente até MATCH_COMPLETED

Consulte os detalhes da conta a cada 15 segundos em um laço com limite de execução. Esse intervalo também mantém o plano Launch dentro do limite de 10 requisições por minuto.

Poll details
curl https://listingsapi.com/api/v4/connected-accounts/4f712c17-4f95-42dd-90f4-97171a2e67b5/details \-H "Authorization: API $LISTINGSAPI_KEY"

O registro é retornado em data.connectedAccountDetails.details e tem os mesmos campos de um registro da lista. requestMatchesStatus é MATCH_IN_PROGRESS enquanto a tarefa está em execução e MATCH_COMPLETED quando as sugestões estão prontas. Completed significa que o processo de associação terminou, não que algo foi vinculado: connectedLocationsCount permanece 0 até você confirmar.

5. Avalie e confirme as sugestões

Cada sugestão associa um dos seus locais (locationInfo, com locationId como seu databaseId) a uma listagem do Google (suggestedLocationInfo). Mostre os dois lados a um operador ou aceite automaticamente quando o nome e a cidade coincidirem.

Suggestions
curl "https://listingsapi.com/api/v4/connected-accounts/4f712c17-4f95-42dd-90f4-97171a2e67b5/connection-suggestions?page=1&perPage=20" \-H "Authorization: API $LISTINGSAPI_KEY"
JSON
{  "data": {    "connectionSuggestionsForAccount": {      "pageInfo": { "hasNextPage": false, "totalRecords": 2 },      "records": [        {          "accountType": "GMB",          "matchedDataDatabaseId": "0d5e306f-0da0-46e3-929f-fd3c67ccd8cc",          "locationId": "73415",          "locationInfo": { "name": "My Business", "city": "Lincoln", "stateIso": "NE" },          "suggestedLocationInfo": { "locationInfo": { "name": "My Business", "city": "Lincoln" } }        }      ]    }  }}

Uma sugestão não tem id. Para confirmá-la, você monta um id de registro de associação: o base64 de <MatchRecordType>:<matchedDataDatabaseId>, com o tipo escolhido entre os valores de accountType. Para o Google (GMB), o tipo é GmbLocationMatchedData, portanto o registro acima é codificado como R21iTG9jYXRpb25NYXRjaGVkRGF0YTowZDVlMzA2Zi0wZGEwLTQ2ZTMtOTI5Zi1mZDNjNjdjY2Q4Y2M=. O Facebook (FB) usa FbLocationMatchedData e a Apple (APPLE) usa AppleLocationMatchedData.

Confirm matches
# base64 of GmbLocationMatchedData:0d5e306f-0da0-46e3-929f-fd3c67ccd8cccurl -X POST https://listingsapi.com/api/v4/connected-accounts/confirm-matches \-H "Authorization: API $LISTINGSAPI_KEY" \-H "Content-Type: application/json" \-d '{ "input": { "matchRecordIds": ["R21iTG9jYXRpb25NYXRjaGVkRGF0YTowZDVlMzA2Zi0wZGEwLTQ2ZTMtOTI5Zi1mZDNjNjdjY2Q4Y2M="] } }'

A resposta é data.confirmConnectMatches com success e failedIds. failedIds contém os valores decodificados de matchedDataDatabaseId que não puderam ser confirmados, como um registro já consumido ou um local arquivado após a associação. Um id montado com o tipo errado não retorna um 400: a chamada retorna 200 com success: false e sem failedIds, portanto verifique success sempre. As sugestões não enviadas permanecem inalteradas.

6. Importe listagens que ainda não têm um local

A correspondência apenas associa listagens a locais que você já tem. Para importar as demais, liste tudo o que a conta pode acessar e crie um local a partir de cada listagem desejada.

Account listings
curl -X POST https://listingsapi.com/api/v4/connected-accounts/connected-account-listings \-H "Authorization: API $LISTINGSAPI_KEY" \-H "Content-Type: application/json" \-d '{ "connectedAccountId": "4f712c17-4f95-42dd-90f4-97171a2e67b5", "perPage": 50 }'
JSON
{  "data": {    "connectedAccountListings": {      "pageInfo": { "hasNextPage": false, "totalRecords": 60 },      "records": [        {          "id": "R21iQnVsa0RhdGFMYWtlOjA2MDQ4NmExLTA0NzQtNDc4NS1iMjNhLTBkOGM4MzhmNGQ5OA==",          "locationName": "Trial",          "address": "123 William St, NY 10038, Manhattan, US",          "liveLink": null        }      ]    }  }}

Envie locationInfo com um termo de busca para filtrar os resultados de uma conta grande por nome, endereço, telefone, código postal ou código da loja. O valor de id em cada registro é o connectedAccountListingId que as próximas duas chamadas recebem. Nenhum dos SDKs oferece suporte a create-location-from-listing ainda, então os exemplos em Python e Node chamam REST diretamente com o mesmo cabeçalho.

Create from listing
curl -X POST https://listingsapi.com/api/v4/connected-accounts/create-location-from-listing \-H "Authorization: API $LISTINGSAPI_KEY" \-H "Content-Type: application/json" \-d '{  "input": {    "connectedAccountId": "4f712c17-4f95-42dd-90f4-97171a2e67b5",    "connectedAccountListingId": "R21iQnVsa0RhdGFMYWtlOjA2MDQ4NmExLTA0NzQtNDc4NS1iMjNhLTBkOGM4MzhmNGQ5OA=="  }}'
JSON
{  "data": {    "createLocationFromConnectedAccountListing": { "success": true, "locationId": 88277, "errors": null }  }}

O local é criado a partir dos dados do Google (nome, endereço, horários, categorias, telefone, atributos) e vinculado à listagem imediatamente. A listagem do Google permanece em IN_PROGRESS até que sua primeira atualização do local seja publicada nela. locationId é simplesmente o databaseId. Em caso de falha, success é false e errors contém um código como SY81067 (o id da listagem não foi encontrado). O campo é connectedAccountListingId; listingId é rejeitado pelo esquema.

Se a listagem pertencer a um local que você já tem, vincule-a em vez de criar uma duplicata.

Link a listing
curl -X POST https://listingsapi.com/api/v4/connected-accounts/connect-listing \-H "Authorization: API $LISTINGSAPI_KEY" \-H "Content-Type: application/json" \-d '{  "input": {    "locationId": "TG9jYXRpb246MTgwMDI4OQ==",    "connectedAccountId": "4f712c17-4f95-42dd-90f4-97171a2e67b5",    "connectedAccountListingId": "R21iQnVsa0RhdGFMYWtlOjA2MDQ4NmExLTA0NzQtNDc4NS1iMjNhLTBkOGM4MzhmNGQ5OA=="  }}'

Uma tentativa de vinculação malsucedida retorna success: false com um message, por exemplo, Listing record not found, ou uma observação de que a listagem já está conectada a outro local.

7. Como alternativa, conecte um único local

Quando você já sabe qual local o proprietário está conectando, pule a etapa de correspondência e crie um link vinculado a esse local. Em caso de sucesso, o proprietário retorna ao seu successUrl, e as credenciais são associadas somente a esse local.

Single-location link
curl -X POST https://listingsapi.com/api/v4/locations/oauth_connect_url \-H "Authorization: API $LISTINGSAPI_KEY" \-H "Content-Type: application/json" \-d '{  "input": {    "locationId": "TG9jYXRpb246MTgwMDI4OQ==",    "site": "GOOGLE",    "successUrl": "https://app.example.com/locations/1800289/connected",    "errorUrl": "https://app.example.com/locations/1800289/connect-failed"  }}'

A resposta é data.createConnectUrl com success, url e errors. O link é de uso único, então crie um novo a cada tentativa. Uma URL de redirecionamento relativa ou que não pode ser interpretada resulta em uma resposta success: true com um null url, então verifique url. Uma chave sem permissão para acessar esse local recebe uma resposta 403 com SY90003.

8. O que acontece em seguida

Depois que uma listagem é vinculada, a linha do Google Maps nas listagens premium do local sai de REQUIRING_ACTION, passa por IN_PROGRESS e chega a SYNCED com um listingUrl. O Google é adicionado automaticamente como fonte de avaliações, então as avaliações começam a chegar à lista de interações, e as atualizações que você faz no local são enviadas ao perfil.

Com uma URL de webhook configurada no painel, você não precisa fazer consultas periódicas. Cada payload contém location_id e data.connected_account_id.

EventoDisparado quandoO que fazer
connection.location_connectedUma listagem é vinculada a um local; data.platform é google.Marque o local como conectado na sua interface.
connection.reauth_requiredAs credenciais da conta foram invalidadas. Nada é sincronizado até que a autorização seja concedida novamente.Crie um novo link (etapa 1) e peça ao proprietário para fazer login novamente.
connection.listing_inaccessibleAs credenciais estão válidas, mas o acesso a essa listagem específica foi removido.Peça ao proprietário para restaurar o acesso no Google ou vincule outra listagem.

Próximas etapas