连接Google Business Profile并导入地点
创建用于连接 Google 的链接,将所有者在 Google 上的商家信息与您的地点匹配,确认匹配结果,并导入尚无对应地点的商家信息。
连接 Google 账号后,即可在 Google 上为地点发布内容并获取报告。在连接账号之前,地点的高级商家信息中的 Google Maps 行会保持 REQUIRING_ACTION,Google 评价不会被拉取,帖子无法发布到 GOOGLE,Google 分析数据会返回 null。连接账号即可解决这 4 个问题。
批量流程(步骤 1 至 6)一次连接整个 Google 账号,并将该账号拥有的每条商家信息与您的地点进行匹配。单地点流程(步骤 7)每次连接 1 个地点:链接与该地点绑定,因此后续无需匹配。
1.创建连接链接并引导所有者打开
链接的作用范围限于拥有该 API 密钥的账号,因此请求体只包含您的两个重定向 URL。引导所有者打开返回的 url;完成操作后,Google 会将其重定向到 successUrl 或 errorUrl。
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" }}'{ "data": { "bulkConnectLinkForGoogle": { "success": true, "url": "https://connect.example.com/oauth?token=8f3c1d92-...", "errors": null } }}上面的 url 是占位符。请引导所有者打开您自己的响应中返回的 url。
链接的有效期为 24 小时。请检查 url 是否非空,不要仅依赖 success。如果所有者的凭据之后过期,请用相同方式创建新链接:现有连接会被刷新,不会重复创建连接。
2.OAuth 返回后列出已连接的账号
当所有者被重定向到您的 successUrl 时,列出 Google 账号。此接口采用偏移量分页:records[] 加上 pageInfo.totalRecords,使用 page 和 perPage 分页。
curl "https://listingsapi.com/api/v4/connected-accounts?publisher=GoogleAccount&page=1&perPage=20" \-H "Authorization: API $LISTINGSAPI_KEY"{ "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 } ] } }}选择 email 对应刚刚同意授权的所有者的记录,并保存其 connectedAccountId。后续每次调用都需要传入此 UUID。
可选的 status 查询筛选条件使用不同的取值(Connected、NotConnected、ConnectionIssue);将记录自身的 status 作为筛选值传回,会返回 400。
3.触发匹配
匹配程序会获取该账号可访问的所有商家资料,并将每份资料与您的一个地点配对。此时只会生成建议,尚未建立任何关联。
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"] } }'响应为 data.connectedAccountsTriggerMatches,包含 success 和 failedIds。success: true 表示任务已加入队列;无法加入队列的账号会列在 failedIds 中。
4.轮询,直到状态为 MATCH_COMPLETED
使用设有终止限制的循环,每 15 秒轮询一次账号详情。这个间隔也能确保 Launch 套餐的请求频率不超过每分钟 10 次。
curl https://listingsapi.com/api/v4/connected-accounts/4f712c17-4f95-42dd-90f4-97171a2e67b5/details \-H "Authorization: API $LISTINGSAPI_KEY"记录在 data.connectedAccountDetails.details 中返回,字段与列表中的记录相同。任务运行时,requestMatchesStatus 为 MATCH_IN_PROGRESS;建议准备就绪时,则为 MATCH_COMPLETED。Completed 表示匹配程序已完成,并不表示已建立任何关联:在您确认之前,connectedLocationsCount 会保持为 0。
5.审核并确认建议
每条建议将您的一个地点(locationInfo,其 databaseId 为 locationId)与一条 Google 商家信息(suggestedLocationInfo)配对。请向操作人员展示双方信息,或在名称和城市一致时自动接受建议。
curl "https://listingsapi.com/api/v4/connected-accounts/4f712c17-4f95-42dd-90f4-97171a2e67b5/connection-suggestions?page=1&perPage=20" \-H "Authorization: API $LISTINGSAPI_KEY"{ "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" } } } ] } }}建议没有 id。要确认建议,您需要构造匹配记录的 id:从 accountType 中选择类型,然后对 <MatchRecordType>:<matchedDataDatabaseId> 进行 base64 编码。对于 Google(GMB),类型为 GmbLocationMatchedData,因此上面的记录编码后为 R21iTG9jYXRpb25NYXRjaGVkRGF0YTowZDVlMzA2Zi0wZGEwLTQ2ZTMtOTI5Zi1mZDNjNjdjY2Q4Y2M=。Facebook(FB)使用 FbLocationMatchedData,Apple(APPLE)使用 AppleLocationMatchedData。
# 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="] } }'响应为 data.confirmConnectMatches,包含 success 和 failedIds。failedIds 包含无法确认的记录所对应的已解码 matchedDataDatabaseId 值,例如记录已被使用,或地点在匹配后已归档。使用错误类型构造的 id 不会导致返回 400:该调用会返回 200,包含 success: false,但不包含 failedIds,因此请每次都检查 success。未提交的建议保持不变。
6. 导入尚未关联地点的商家信息
匹配只会将商家信息与您已有的地点配对。要导入其余商家信息,请先列出该账号可见的所有商家信息,再根据您需要的每条商家信息创建地点。
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 }'{ "data": { "connectedAccountListings": { "pageInfo": { "hasNextPage": false, "totalRecords": 60 }, "records": [ { "id": "R21iQnVsa0RhdGFMYWtlOjA2MDQ4NmExLTA0NzQtNDc4NS1iMjNhLTBkOGM4MzhmNGQ5OA==", "locationName": "Trial", "address": "123 William St, NY 10038, Manhattan, US", "liveLink": null } ] } }}传入 locationInfo 并指定搜索词,即可按名称、地址、电话、邮政编码或门店代码缩小大型账号的搜索范围。每条记录中的 id 就是后续 2 次调用接受的 connectedAccountListingId。这 2 个 SDK 都尚未封装 create-location-from-listing,因此 Python 和 Node 示例使用相同的请求头直接调用 REST。
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==" }}'{ "data": { "createLocationFromConnectedAccountListing": { "success": true, "locationId": 88277, "errors": null } }}地点根据 Google 数据(名称、地址、营业时间、类别、电话、属性)创建,并立即关联到该商家信息。Google 商家信息会保持 IN_PROGRESS 状态,直到您首次更新地点并将更新发布到该商家信息。locationId 就是普通的 databaseId。失败时,success 为 false,errors 中会包含 SY81067 等代码(商家信息 id 无法解析)。字段名为 connectedAccountListingId;listingId 会被模式校验拒绝。
如果商家信息属于您已有的地点,请将其关联到该地点,避免创建重复地点。
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==" }}'关联失败时会返回 success: false,其中包含 message,例如 Listing record not found,或者一条说明该商家信息已连接到其他地点的提示。
7. 改为连接单个地点
如果您已经知道所有者要连接哪个地点,可以跳过匹配,创建绑定到该地点的链接。成功后,所有者会返回您的 successUrl,凭据仅关联到该地点。
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" }}'响应为 data.createConnectUrl,其中包含 success、url 和 errors。该链接只能使用 1 次,因此每次尝试都需要创建新链接。如果重定向 URL 是相对地址或无法解析,则会返回 success: true,其中 null 为 url,因此请检查 url。无权访问此地点的密钥会收到 403,其中包含 SY90003。
8. 后续处理
商家信息关联后,地点的高级商家信息列表中的 Google Maps 行会从 REQUIRING_ACTION 变为 IN_PROGRESS,最终变为 SYNCED,并包含 listingUrl。Google 会自动添加为评价来源,因此评价会开始出现在互动列表中,您对地点所做的更新也会同步到商家资料。
在控制台中设置 webhook URL 后,您就无需轮询。每个载荷都包含 location_id 和 data.connected_account_id。
后续步骤
- 创建 Google Business Profile:适用于没有 Google 商家信息可供匹配的地点。
- 连接 Facebook 公共主页:对另一个 OAuth 发布平台使用相同的流程。
- 检查商家信息状态和线上链接以及获取评价:查看陆续收到的结果。
- SDK 参考:Python 已连接账号和Node 已连接账号。
- 参考:连接 Google 账号、触发地点匹配、确认连接匹配、获取已连接账号的商家信息、根据商家信息创建地点以及已连接账号索引。