Facebook 페이지 연결

Facebook 연결 링크를 만들고, 소유자의 페이지를 사업장과 매칭하고, 연결을 확인하거나 직접 선택하고, 고객이 서비스 이용을 종료하면 계정 연결을 해제합니다.

Facebook 계정을 연결하면 Facebook에서 사업장의 콘텐츠를 게시하고 보고서를 조회할 수 있습니다. 페이지가 연결되면 게시물의 postSites에서 FACEBOOK을 대상으로 지정할 수 있고, Facebook 분석 엔드포인트는 null 대신 페이지 지표를 반환하며, 페이지가 리뷰 소스로 추가되어 해당 페이지의 리뷰도 다른 리뷰와 함께 수집되고, 사업장의 프리미엄 등록 정보에서 Facebook 행이 REQUIRING_ACTION 상태를 벗어납니다.

흐름은 Google과 같습니다. 링크를 만들고, 소유자가 동의하도록 한 다음, 매칭하고 확인합니다. Facebook에서 다른 값을 사용하는 경우에는 별도로 명시합니다.

Facebook 페이지에는 Facebook에서 영업시간이 이미 설정되어 있어야 합니다. 사업장에 businessHours가 있어도 Facebook은 영업시간이 없는 페이지에 대한 ListingsAPI의 업데이트를 거부합니다. 그러면 Facebook 등록 정보는 영업시간 누락에 관한 syncIssue와 함께 IN_PROGRESS 상태로 유지됩니다. 이 문제를 해결하려면 Facebook에서 페이지에 영업시간을 추가한 다음 사업장 업데이트를 전송합니다.

본문에는 리디렉션 URL 2개만 포함합니다. 링크의 범위는 키를 소유한 계정으로 한정되며, 24시간 동안 유효합니다.

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

위의 url은 자리표시자입니다. 직접 받은 응답에서 반환된 url로 소유자를 안내합니다.

소유자를 url로 리디렉션합니다. 소유자는 Facebook 약관에 동의하고 페이지 권한을 부여한 후 애플리케이션의 successUrl로 이동합니다.

2. OAuth에서 돌아온 후 연결된 계정 목록 조회

publisher=FacebookAccount로 필터링합니다. 이는 오프셋 기반 페이지로, records[]와 pageInfo.totalRecords로 구성되며 page와 perPage로 페이지를 나눕니다.

List accounts
curl "https://listingsapi.com/api/v4/connected-accounts?publisher=FacebookAccount&page=1&perPage=20" \-H "Authorization: API $LISTINGSAPI_KEY"
JSON
{  "data": {    "connectedAccountsInfo": {      "pageInfo": { "hasNextPage": false, "totalRecords": 1 },      "records": [        {          "connectedAccountId": "d2397854-52c2-41d7-95f1-b90cba16498d",          "connectedAccountType": "FacebookAccount",          "status": "CONNECTED",          "requestMatchesStatus": "MATCH_COMPLETED",          "connectedLocationsCount": 0        }      ]    }  }}

connectedAccountId를 저장해 둡니다. status는 CONNECTED, MATCH_IN_PROGRESS 또는 CONNECTIVITY_ISSUE이며, CONNECTED 이외의 값이면 소유자가 다시 승인해야 다음 단계가 작동합니다.

3. 매칭을 실행하고 완료될 때까지 대기

매칭은 계정이 접근할 수 있는 페이지를 가져와 각 페이지를 사업장 하나와 짝지어 줍니다. 백그라운드에서 실행되므로 requestMatchesStatus가 MATCH_COMPLETED가 될 때까지 계정 세부 정보를 폴링합니다. 그 전에 제안 목록을 조회하면 빈 records 배열이 반환되어 "매칭 결과 없음"처럼 보입니다.

Trigger and poll
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": ["d2397854-52c2-41d7-95f1-b90cba16498d"] } }' # then, every 15 seconds until requestMatchesStatus is MATCH_COMPLETEDcurl https://listingsapi.com/api/v4/connected-accounts/d2397854-52c2-41d7-95f1-b90cba16498d/details \-H "Authorization: API $LISTINGSAPI_KEY"

세부 정보 레코드는 data.connectedAccountDetails.details에서 반환됩니다. MATCH_COMPLETED는 매칭 작업이 완료되었음을 의미합니다. 확인하기 전까지는 아무것도 연결되지 않으므로 connectedLocationsCount는 아직 0 상태로 유지됩니다.

4. 제안 검토 및 확인

각 레코드는 사업장(locationInfo, locationId)을 페이지(suggestedLocationInfo)와 짝지어 줍니다. Facebook 계정의 경우 accountType은 GMB가 아니라 FB이며, 이에 따라 확인 요청에 보내는 id가 달라집니다.

Suggestions
curl "https://listingsapi.com/api/v4/connected-accounts/d2397854-52c2-41d7-95f1-b90cba16498d/connection-suggestions?page=1&perPage=20" \-H "Authorization: API $LISTINGSAPI_KEY"

제안에는 id가 없습니다. accountType에서 유형을 선택하고 <MatchRecordType>:<matchedDataDatabaseId>를 base64로 인코딩하여 생성합니다. 참조 문서에는 Google 예시만 나와 있으며, 이를 디코딩하면 GmbLocationMatchedData:...가 됩니다. 유형은 게시 플랫폼마다 다릅니다. Facebook에서는 유형이 FbLocationMatchedData이므로 0d5e306f-0da0-46e3-929f-fd3c67ccd8cc를 사용하는 FB는 RmJMb2NhdGlvbk1hdGNoZWREYXRhOjBkNWUzMDZmLTBkYTAtNDZlMy05MjlmLWZkM2M2N2NjZDhjYw==로 인코딩됩니다.

accountType매칭 레코드 유형
GMBGmbLocationMatchedData
FBFbLocationMatchedData
APPLEAppleLocationMatchedData
Confirm matches
# base64 of FbLocationMatchedData: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": ["RmJMb2NhdGlvbk1hdGNoZWREYXRhOjBkNWUzMDZmLTBkYTAtNDZlMy05MjlmLWZkM2M2N2NjZDhjYw=="] } }'

응답은 data.confirmConnectMatches이며, success와 확인하지 못한 디코딩된 데이터베이스 id인 failedIds를 포함합니다. 잘못된 유형으로 만든 id를 사용하면 success: false가 포함되고 failedIds는 없는 200이 반환되므로 항상 success를 확인합니다.

매칭 결과가 확실하지 않거나 매칭 실행 후 페이지가 생성된 경우, 계정에서 볼 수 있는 페이지 목록을 조회하고 페이지 하나를 직접 연결합니다. connectedAccountId는 등록 정보 호출의 JSON 본문에 넣습니다. 쿼리 매개변수로 전달하면 무시되며 첫 번째 연결 계정의 등록 정보가 반환됩니다.

Pick and link
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": "d2397854-52c2-41d7-95f1-b90cba16498d", "locationInfo": "Lincoln" }' 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": "d2397854-52c2-41d7-95f1-b90cba16498d",    "connectedAccountListingId": "<id from the listings response>"  }}'

각 등록 정보 레코드에는 id, locationName, address, liveLink가 포함됩니다. 레코드의 id는 connect-listing이 받는 connectedAccountListingId이며, 필드 이름은 listingId가 아닙니다. 연결에 실패하면 Listing record not found와 같은 message와 함께 success: false가 반환됩니다.

6. 고객이 이용을 종료하면 계정 연결 해제

계정 연결은 전체 단위로만 해제할 수 있습니다. 계정을 통해 연결된 모든 페이지의 동기화가 중지되고 Facebook 상호작용도 더 이상 수신되지 않습니다. 계정을 유지하면서 사업장 하나만 연결 해제하려면 disconnect-listing을 사용합니다.

Disconnect
curl -X POST https://listingsapi.com/api/v4/connected-accounts/disconnect-facebook \-H "Authorization: API $LISTINGSAPI_KEY" \-H "Content-Type: application/json" \-d '{ "input": { "connectedAccountId": "d2397854-52c2-41d7-95f1-b90cba16498d" } }'

응답은 success를 포함한 data.fbBulkDisconnect입니다. 알 수 없는 connectedAccountId에 대해서도 true이므로, 이는 "처리됨"을 의미하며 "활성 연결이 제거됨"을 의미하지는 않습니다. 확실히 확인해야 한다면 연결된 계정 목록을 다시 조회합니다.

7. 이후 진행 과정

연결된 각 사업장에 대해 data.platform: "facebook"을 포함한 connection.location_connected 이벤트가 발생하며, 연결을 해제하면 connection.location_disconnected 이벤트가 발생합니다. Facebook이 권한 부여를 무효화하면 connection.reauth_required 이벤트를 수신합니다. 이 경우 새 링크를 생성하고(1단계) 소유자에게 모든 권한에 다시 동의하도록 요청합니다. 연결되면 사업장의 프리미엄 등록 정보에서 Facebook 행이 SYNCED로 변경되고, postSites: ["FACEBOOK"]이 유효한 대상이 되며, Facebook 분석 엔드포인트가 데이터를 반환하기 시작합니다.

다음 단계