연결된 계정
listingsapi-js SDK로 Google, Facebook, Apple Business Connect 계정을 연결하고, 각 계정의 등록 정보를 사업장과 매칭하고, 계정 연결을 해제합니다.
연결된 계정은 Google Business Profile, Facebook Pages 또는 Apple Business Connect 소유자가 OAuth로 부여한 접근 권한입니다. 권한이 부여되면 플랫폼은 해당 계정이 소유한 등록 정보를 읽고 각 등록 정보를 사업장에 연결할 수 있습니다. 연결된 계정과 관련된 모든 메서드는 ListingsAPI 클라이언트 인스턴스에 있습니다.
일반적인 순서는 연결 링크를 생성하고, 소유자가 권한을 부여할 때까지 기다린 다음, 계정 목록을 조회하여 connectedAccountId을 얻고, 매칭을 실행하고, 제안을 검토한 후 확정하거나 등록 정보를 수동으로 연결하는 것입니다. 각 메서드는 해당 응답 키 아래의 페이로드를 반환하며, 이 키는 아래 각 섹션에 명시되어 있습니다.
connectGoogleAccount
Google Business Profile에 대한 계정 전체 범위의 OAuth 링크를 생성합니다. 소유자를 반환된 url로 이동시키면 동의 화면이 닫힐 때 지정한 successUrl 또는 errorUrl로 돌아옵니다.
const link = await client.connectGoogleAccount('https://app.example.com/onboarding/google/done','https://app.example.com/onboarding/google/failed',); console.log(link.url);매개변수
bulkConnectLinkForGoogle 페이로드를 반환하며, 여기에는 url, success, errors이 포함됩니다. 사용할 수 없는 리디렉션이라도 url이 null인 성공 응답으로 반환될 수 있으므로 success뿐 아니라 url도 확인해야 합니다. 링크의 유효 기간이 짧으므로 시도할 때마다 새 링크를 생성합니다.
connectFacebookAccount
connectGoogleAccount에 해당하는 Facebook Pages용 메서드이며, 동일한 리디렉션 인수 2개를 사용합니다.
const link = await client.connectFacebookAccount('https://app.example.com/onboarding/facebook/done','https://app.example.com/onboarding/facebook/failed',); console.log(link.url);매개변수
bulkConnectLinkForFacebook 페이로드를 반환하며, 여기에는 url, success, errors이 포함됩니다.
getOauthConnectUrl
계정 전체가 아닌 사업장 1개로 범위를 제한한 OAuth 링크를 생성합니다. 소유자가 연결할 사업장을 이미 알고 있으며, 연결 후 자체 제품의 해당 사업장 화면으로 돌아오도록 하려는 경우 사용합니다.
const link = await client.getOauthConnectUrl(1800289,'GOOGLE','https://app.example.com/locations/1800289/connected','https://app.example.com/locations/1800289/connect-failed',); console.log(link.url);매개변수
createConnectUrl 페이로드를 반환하며, 여기에는 url, success, errors이 포함됩니다. 두 리디렉션 URL은 모두 필수이며 절대 URL이어야 합니다. 링크는 1회만 사용할 수 있으며 지정한 사업장에 연결됩니다.
fetchConnectedAccounts
현재 계정에서 접근 권한을 부여받은 Google 및 Facebook 계정 목록을 연결 상태 및 연결된 사업장 수와 함께 조회합니다. 이후 모든 메서드에 필요한 connectedAccountId을 여기서 얻습니다.
const page1 = await client.fetchConnectedAccounts({publisher: 'GoogleAccount',status: 'Connected',page: 1,perPage: 20,}); for (const record of page1.records ?? []) {console.log(record.email, record.connectedAccountId, record.status);}옵션
connectedAccountsInfo 페이로드를 반환하며, 여기에는 records 배열과 hasNextPage, hasPreviousPage, totalPages, totalRecords이 포함된 pageInfo가 있습니다. 각 레코드에는 connectedAccountId, email, connectedAccountType, connectedLocationsCount, connectivityIssue, status, requestMatchesStatus이 포함됩니다.
필터와 필드에서 사용하는 값은 서로 다릅니다. status 옵션은 'Connected', 'NotConnected' 또는 'ConnectionIssue'을 받지만, 레코드 자체의 status 값은 CONNECTED, MATCH_IN_PROGRESS 또는 CONNECTIVITY_ISSUE입니다. 레코드의 값을 필터로 다시 입력하면 거부됩니다.
fetchConnectedAccountDetails
ID로 계정 1개를 조회합니다. ID를 이미 알고 있다면 전체 목록을 페이지별로 조회하는 것보다 비용이 적게 들며, 매칭이 실행되는 동안 폴링할 때도 이 메서드를 사용합니다.
const details = await client.fetchConnectedAccountDetails('4f712c17-4f95-42dd-90f4-97171a2e67b5',); console.log(details.details.requestMatchesStatus); // MATCH_IN_PROGRESS, then MATCH_COMPLETED매개변수
connectedAccountDetails 페이로드를 반환하며, 레코드는 details 아래에 중첩되어 있고 목록 조회에서 반환하는 것과 동일한 필드를 포함합니다. requestMatchesStatus를 확인하여 제안이 준비되었는지 파악하고, status과 connectivityIssue를 읽어 권한을 다시 부여하도록 요청할지 결정합니다.
fetchConnectedAccountFolders
연결된 계정이 접근할 수 있는 Google 계정 그룹(폴더) 목록을 조회합니다. 소유자가 새 등록 정보를 특정 그룹에 추가하려는 경우 createGmbListing 전에 호출합니다.
const folders = await client.fetchConnectedAccountFolders('4f712c17-4f95-42dd-90f4-97171a2e67b5',); for (const folder of folders) {console.log(folder.folderId, folder.folderName, folder.locationCount);} // Narrow by nameconst matching = await client.fetchConnectedAccountFolders('4f712c17-4f95-42dd-90f4-97171a2e67b5',{ folderName: 'West Region' },);옵션
getFoldersUnderGoogleAccount 배열을 반환하며, 기본값은 빈 배열입니다. 각 폴더에는 folderId(변경 없이 그대로 전달하는 accounts/<id> 문자열), folderName, locationCount가 포함되며, Google에서 개수를 제공하지 않으면 마지막 값은 null일 수 있습니다. 이 경로는 Google 유형 계정에서만 유효합니다.
fetchConnectedAccountListings
연결된 계정이 접근할 수 있는 게시 플랫폼의 등록 정보 목록을 조회합니다. 각 레코드의 id은 connectListing에서 받는 connectedAccountListingId과 정확히 같으므로, 이를 사용하여 등록 정보 선택기를 구현합니다.
const listings = await client.fetchConnectedAccountListings('4f712c17-4f95-42dd-90f4-97171a2e67b5',{ locationInfo: 'William St', page: 1, perPage: 50 },); for (const record of listings.records ?? []) {console.log(record.id, record.locationName, record.address);}옵션
connectedAccountListings 페이로드를 반환하며, 여기에는 records과 pageInfo가 포함됩니다. 각 레코드에는 id, locationName, address, phone, liveLink, accountTypeName이 포함됩니다. 내부적으로 쓰기 형태의 요청을 사용하지만 읽기 작업이며, SDK가 엔드포인트의 요구 사항에 따라 계정 ID와 페이지 정보를 요청 본문에 자동으로 넣습니다.
triggerConnectedAccountMatches
지정한 계정이 접근할 수 있는 모든 프로필을 가져와 현재 계정의 사업장과 매칭하는 작업을 대기열에 추가합니다. 소유자가 동의 화면에서 절차를 마친 직후 호출하고, 사업장을 일괄로 생성한 후 다시 호출합니다.
const result = await client.triggerConnectedAccountMatches(['4f712c17-4f95-42dd-90f4-97171a2e67b5',]); console.log(result.success, result.failedIds);매개변수
connectedAccountsTriggerMatches 페이로드를 반환하며, 여기에는 success과 failedIds가 포함됩니다. success이 true이면 작업이 대기열에 추가되었다는 뜻이며, 매칭이 완료되었다는 뜻은 아닙니다. requestMatchesStatus 값이 MATCH_COMPLETED이 될 때까지 fetchConnectedAccountDetails를 폴링한 다음 제안을 조회합니다.
fetchConnectionSuggestions
연결을 수행하기 전에 운영자가 각 사업장과 게시 플랫폼의 등록 정보를 비교할 수 있도록 매칭으로 생성된 연결 후보 쌍을 조회합니다.
const suggestions = await client.fetchConnectionSuggestions('4f712c17-4f95-42dd-90f4-97171a2e67b5',{ page: 1, perPage: 50 },); for (const record of suggestions.records ?? []) {console.log(record.accountType, record.matchedDataDatabaseId, record.locationInfo.name);}옵션
connectionSuggestionsForAccount 페이로드를 반환하며, 여기에는 records과 pageInfo가 포함됩니다. 제안 레코드에는 id 필드가 없습니다. 식별자는 matchedDataDatabaseId이며, accountType(GMB, FB 또는 APPLE)는 매칭 레코드의 유형을 나타냅니다. confirmConnectedAccountMatches에서 받는 ID를 구성하려면 두 값이 모두 필요하므로 함께 보관합니다. 아직 매칭 결과가 없는 계정은 빈 records 배열을 반환합니다.
confirmConnectedAccountMatches
검토한 연결 후보 쌍을 승인합니다. 확정하면 각 사업장이 해당 게시 플랫폼의 등록 정보에 연결되어 이후 사업장 업데이트가 반영됩니다.
제안 레코드에서 각 ID를 구성하려면 매칭 레코드 유형 이름과 레코드의 matchedDataDatabaseId을 콜론으로 연결한 다음 base64로 인코딩합니다. GMB은 GmbLocationMatchedData에, FB은 FbLocationMatchedData에, APPLE는 AppleLocationMatchedData에 매핑됩니다.
const TYPES: Record<string, string> = {GMB: 'GmbLocationMatchedData',FB: 'FbLocationMatchedData',APPLE: 'AppleLocationMatchedData',}; const matchRecordId = (record: any) =>Buffer.from(TYPES[record.accountType] + ':' + record.matchedDataDatabaseId).toString('base64'); const approved = (suggestions.records ?? []).map(matchRecordId);const result = await client.confirmConnectedAccountMatches(approved); console.log(result.success, result.failedIds);매개변수
confirmConnectMatches 페이로드를 반환하며, 여기에는 success과 failedIds가 포함됩니다. 호출할 때마다 success을 확인해야 하며, ID를 디코딩한 결과가 3가지 유형 중 하나가 아니면 success가 false이고 failedIds가 없는 성공 형식의 응답이 반환됩니다. 일부 ID의 처리가 실패하면 failedIds에는 전송한 인코딩 값이 아니라 디코딩된 데이터베이스 ID가 포함되므로, 이를 matchedDataDatabaseId과 대조합니다.
등록 정보 1개를 사업장 1개에 연결하기
다음 3개 메서드는 매칭된 등록 정보 1개와 사업장 1개 사이의 연결을 처리하며, 중복으로 설명하지 않고 다른 등록 정보 엔드포인트와 함께 설명합니다:
- connectListing는 매칭된 등록 정보를 사업장에 연결합니다.
- disconnectListing는 해당 연결을 해제합니다.
- createGmbListing는 Google Business Profile이 없는 사업장을 위해 fetchConnectedAccountFolders에서 가져온 폴더 안에 새 Google Business Profile을 생성합니다.
confirmConnectedAccountMatches가 계정의 대부분을 처리한 후에도 매장 1개를 수동으로 연결해야 할 때 이 메서드들을 사용합니다.
oauthDisconnect
사업장별 OAuth 경로를 통해 동일한 단일 사업장 연결 해제 작업을 수행합니다. 동일한 인수를 받고 동일한 페이로드로 이행되므로 코드에서 더 읽기 쉬운 이름을 선택합니다.
await client.oauthDisconnect(1800289, 'GOOGLE');매개변수
disconnectConnectedAccountsLocations 페이로드로 이행되며, 이는 disconnectListing가 반환하는 것과 동일한 키입니다.
disconnectGoogleAccount
Google 계정 전체의 연결을 해제합니다. 해당 계정을 통해 연결된 모든 사업장이 더 이상 업데이트를 받지 않습니다. 고객이 서비스 이용을 중단하거나 소유권을 이전할 때 사용합니다.
await client.disconnectGoogleAccount('4f712c17-4f95-42dd-90f4-97171a2e67b5');매개변수
success가 포함된 gmbBulkDisconnect 페이로드로 이행됩니다. 이 작업은 전체에 적용되며 일부에만 적용할 수 없습니다. 계정을 유지하면서 사업장 1개의 연결만 해제하려면 disconnectListing를 사용합니다. 알 수 없는 ID에도 success 값으로 true가 반환되므로 확실히 확인해야 한다면 이후에 fetchConnectedAccounts를 조회합니다.
disconnectFacebookAccount
Facebook에서 같은 작업을 수행하며, 동일한 인수를 받고 마찬가지로 전체에 적용되거나 전혀 적용되지 않습니다.
await client.disconnectFacebookAccount('9d2b5a41-0c7e-4f83-bb16-2ac43e70d915');매개변수
success가 포함된 fbBulkDisconnect 페이로드로 이행됩니다. 동일한 주의 사항이 적용됩니다. 알 수 없는 ID에도 성공을 반환하므로 fetchConnectedAccounts로 확인합니다.
일반적인 온보딩 워크플로
import { ListingsAPI } from 'listingsapi-js'; const client = new ListingsAPI(); // reads LISTINGSAPI_KEY from env // 1. Send the owner through the consent screenconst link = await client.connectGoogleAccount('https://app.example.com/onboarding/google/done','https://app.example.com/onboarding/google/failed',);console.log('open:', link.url); // 2. After they return, pick up the account IDconst accounts = await client.fetchConnectedAccounts({ publisher: 'GoogleAccount' });const accountId = accounts.records[0].connectedAccountId; // 3. Match its listings against your locationsawait client.triggerConnectedAccountMatches([accountId]); // 4. Poll until matching finisheslet details = await client.fetchConnectedAccountDetails(accountId);while (details.details.requestMatchesStatus !== 'MATCH_COMPLETED') {await new Promise((resolve) => setTimeout(resolve, 5000));details = await client.fetchConnectedAccountDetails(accountId);} // 5. Read the suggestions and confirm the approved onesconst suggestions = await client.fetchConnectionSuggestions(accountId, { perPage: 100 });console.log('found ' + (suggestions.records ?? []).length + ' suggested matches');관련 자료
- 등록 정보, 등록 정보 관점에서 설명하는 동일한 연결 및 연결 해제 메서드
- 사업장, 사업장 ID 조회
- 오류 처리, 모든 메서드에서 발생시키는 타입이 지정된 오류
- 연결된 계정 엔드포인트, 이 메서드에 해당하는 REST 사용 절차
- Google 연결 및 사업장 가져오기, 전체 온보딩 가이드
- Facebook 페이지 연결, Facebook용 가이드
- Google Business Profile 생성,
createGmbListing가이드 - REST 참조: 계정 목록 조회, 계정 세부 정보, 폴더, 계정 등록 정보, 매칭 실행, 연결 제안, 매칭 확정, 등록 정보 연결, 등록 정보 연결 해제