連結Google Business Profile並匯入地點
建立用於連結 Google 的連結,將擁有者的 Google 商家資訊與您的地點配對,確認配對結果,並匯入尚未對應地點的商家資訊。
連結 Google 帳戶後,即可為地點在 Google 上發布內容及取得報表。在連結帳戶之前,地點的進階商家資訊中,Google Maps 那一列會維持 REQUIRING_ACTION,系統不會匯入 Google 評論,貼文無法發布至 GOOGLE,而 Google 分析資料會傳回 null。連結帳戶即可解決這 4 項問題。
批次流程(步驟 1 至 6)只需連結整個 Google 帳戶一次,即可將該帳戶擁有的每筆商家資訊與您的地點進行比對。單一地點流程(步驟 7)每次連結 1 個地點:連結會綁定該地點,因此後續不需要比對步驟。
1. 建立連結帳戶用的連結,並將擁有者重新導向至該連結
此連結的適用範圍僅限於擁有該 API 金鑰的帳戶,因此請求主體只包含您的 2 個重新導向 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 是否為非 null 值,不要只依據 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:將 <MatchRecordType>:<matchedDataDatabaseId> 以 base64 編碼,其中的類型從 accountType 中選取。對於 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,並包含值為 url 的 null,因此請檢查 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 帳戶、觸發地點比對、確認連結比對結果、擷取已連結帳戶的商家資訊、從商家資訊建立地點,以及已連結帳戶索引。