Akun terhubung

Hubungkan akun Google, Facebook, dan Apple Business Connect, cocokkan profil bisnisnya dengan lokasi, dan putuskan koneksinya melalui SDK listingsapi-js.

Akun terhubung adalah pemberian izin OAuth oleh pemilik Google Business Profile, Facebook Pages, atau Apple Business Connect. Setelah izin diberikan, platform dapat membaca profil bisnis yang dimiliki akun tersebut dan menautkan masing-masing ke suatu lokasi. Semua metode akun terhubung tersedia pada instans klien ListingsAPI.

Urutan yang umum adalah: buat tautan koneksi, tunggu pemilik memberikan izin, ambil daftar akun untuk mendapatkan connectedAccountId, mulai pencocokan, tinjau saran, lalu konfirmasikan saran tersebut atau tautkan profil bisnis secara manual. Setiap metode menghasilkan payload di bawah kunci responsnya sendiri, yang disebutkan di setiap bagian di bawah ini.

connectGoogleAccount

Buat tautan OAuth yang mencakup seluruh akun untuk Google Business Profile. Arahkan pemilik ke url yang dikembalikan; mereka akan kembali ke successUrl atau errorUrl Anda ketika layar persetujuan ditutup.

TypeScript
const link = await client.connectGoogleAccount('https://app.example.com/onboarding/google/done','https://app.example.com/onboarding/google/failed',); console.log(link.url);

Parameter

ParameterTipeDeskripsi
successUrlstringURL absolut tujuan pemilik kembali setelah memberikan izin.
errorUrlstringURL absolut tujuan pemilik kembali jika mereka membatalkan atau pemberian izin gagal.

Menghasilkan payload bulkConnectLinkForGoogle: url, success, dan errors. Periksa url dan bukan hanya success, karena pengalihan yang tidak dapat digunakan bisa dikembalikan sebagai keberhasilan dengan url bernilai null. Tautan ini memiliki masa berlaku singkat, jadi buat tautan baru untuk setiap percobaan.

connectFacebookAccount

Padanan connectGoogleAccount untuk Facebook Pages, dengan dua argumen pengalihan yang sama.

TypeScript
const link = await client.connectFacebookAccount('https://app.example.com/onboarding/facebook/done','https://app.example.com/onboarding/facebook/failed',); console.log(link.url);

Parameter

ParameterTipeDeskripsi
successUrlstringURL absolut tujuan pemilik kembali setelah memberikan izin.
errorUrlstringURL absolut tujuan pemilik kembali jika mereka membatalkan atau pemberian izin gagal.

Menghasilkan payload bulkConnectLinkForFacebook: url, success, dan errors.

getOauthConnectUrl

Buat tautan OAuth yang cakupannya terbatas pada satu lokasi, bukan seluruh akun. Gunakan tautan ini ketika Anda sudah mengetahui lokasi yang akan dihubungkan oleh pemilik dan ingin mereka kembali ke layar lokasi tersebut di produk Anda sendiri.

TypeScript
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);

Parameter

ParameterTipeDeskripsi
locationIdstring | numberLokasi yang dikaitkan dengan koneksi. ID numerik dikodekan secara otomatis untuk Anda.
sitestringPlatform publikasi yang akan dihubungkan: 'GOOGLE', 'FACEBOOK', atau 'APPLE'.
successUrlstringURL absolut tujuan pemilik kembali setelah memberikan izin.
errorUrlstringURL absolut tujuan pemilik kembali jika pemberian izin gagal.

Menghasilkan payload createConnectUrl: url, success, dan errors. Kedua URL pengalihan wajib diisi dan harus absolut. Tautan ini hanya dapat digunakan sekali dan terikat pada lokasi yang Anda tentukan.

fetchConnectedAccounts

Ambil daftar akun Google dan Facebook yang telah diberi izin pada akun Anda, beserta kondisi koneksi dan jumlah lokasi yang tertaut. Dari sini Anda mendapatkan connectedAccountId yang dibutuhkan oleh setiap metode berikutnya.

TypeScript
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);}

Opsi

ParameterTipeDeskripsi
publisherstringTipe akun, misalnya 'GoogleAccount' atau 'FacebookAccount'.
statusstringFilter status koneksi: 'Connected', 'NotConnected', atau 'ConnectionIssue'.
pagenumberNomor halaman (dimulai dari 1).
perPagenumberJumlah rekaman per halaman.

Menghasilkan payload connectedAccountsInfo: array records beserta pageInfo yang berisi hasNextPage, hasPreviousPage, totalPages, dan totalRecords. Setiap rekaman memuat connectedAccountId, email, connectedAccountType, connectedLocationsCount, connectivityIssue, status, dan requestMatchesStatus.

Filter dan field menggunakan istilah nilai yang berbeda. Opsi status menerima 'Connected', 'NotConnected', atau 'ConnectionIssue', sedangkan status pada rekaman bernilai CONNECTED, MATCH_IN_PROGRESS, atau CONNECTIVITY_ISSUE. Penggunaan nilai dari rekaman sebagai filter akan ditolak.

fetchConnectedAccountDetails

Baca satu akun berdasarkan ID-nya. Cara ini memerlukan lebih sedikit sumber daya daripada menelusuri seluruh halaman daftar jika Anda sudah memiliki ID tersebut, dan merupakan metode yang digunakan untuk polling selama pencocokan berlangsung.

TypeScript
const details = await client.fetchConnectedAccountDetails('4f712c17-4f95-42dd-90f4-97171a2e67b5',); console.log(details.details.requestMatchesStatus); // MATCH_IN_PROGRESS, then MATCH_COMPLETED

Parameter

ParameterTipeDeskripsi
connectedAccountIdstringID akun terhubung, diperoleh dari fetchConnectedAccounts.

Menghasilkan payload connectedAccountDetails, yang menempatkan rekaman di bawah details dengan field yang sama seperti yang dikembalikan oleh daftar. Pantau requestMatchesStatus untuk mengetahui kapan saran siap, dan baca status beserta connectivityIssue untuk menentukan apakah perlu meminta pemberian izin ulang.

fetchConnectedAccountFolders

Ambil daftar grup akun Google (folder) yang dapat diakses oleh akun terhubung. Panggil metode ini sebelum createGmbListing ketika pemilik menginginkan profil bisnis baru berada dalam grup tertentu.

TypeScript
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' },);

Opsi

ParameterTipeDeskripsi
folderNamestringBatasi hasil pada folder yang cocok dengan nama ini.

Menghasilkan array getFoldersUnderGoogleAccount, dengan array kosong sebagai nilai default. Setiap folder memuat folderId (string accounts/<id> yang Anda teruskan tanpa perubahan), folderName, dan locationCount, yang dapat bernilai null ketika Google tidak melaporkan jumlahnya. Path ini hanya valid untuk akun bertipe Google.

fetchConnectedAccountListings

Ambil daftar profil bisnis pada platform publikasi yang dapat diakses oleh akun terhubung. id pada setiap rekaman sama persis dengan connectedAccountListingId yang diterima oleh connectListing, sehingga Anda dapat menggunakannya untuk membuat pemilih profil bisnis.

TypeScript
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);}

Opsi

ParameterTipeDeskripsi
locationInfostringPencarian teks bebas pada nama bisnis, alamat, wilayah, kode pos, kode toko, dan nomor telepon.
pagenumberNomor halaman (dimulai dari 1).
perPagenumberJumlah rekaman per halaman. Nilai default adalah 500, yang juga merupakan nilai maksimum.

Menghasilkan payload connectedAccountListings: records beserta pageInfo. Setiap rekaman memuat id, locationName, address, phone, liveLink, dan accountTypeName. Meskipun permintaan yang dikirim menggunakan format operasi tulis, ini adalah operasi baca: SDK menempatkan ID akun dan informasi paginasi dalam body permintaan untuk Anda, sesuai persyaratan endpoint.

triggerConnectedAccountMatches

Masukkan ke antrean tugas yang mengambil setiap profil yang dapat diakses oleh akun-akun yang ditentukan dan mencocokkannya dengan lokasi Anda. Panggil metode ini segera setelah pemilik menyelesaikan proses di layar persetujuan, dan panggil kembali setelah Anda membuat lokasi secara massal.

TypeScript
const result = await client.triggerConnectedAccountMatches(['4f712c17-4f95-42dd-90f4-97171a2e67b5',]); console.log(result.success, result.failedIds);

Parameter

ParameterTipeDeskripsi
connectedAccountIdsstring[]Akun-akun yang akan menjalani pencocokan.

Menghasilkan payload connectedAccountsTriggerMatches: success dan failedIds. Nilai true pada success berarti tugas telah dimasukkan ke antrean, bukan bahwa pencocokan telah selesai. Lakukan polling pada fetchConnectedAccountDetails hingga requestMatchesStatus bernilai MATCH_COMPLETED, lalu baca sarannya.

fetchConnectionSuggestions

Baca pasangan yang dihasilkan oleh pencocokan agar operator dapat membandingkan setiap lokasi dengan profil bisnis pada platform publikasi sebelum penautan apa pun dilakukan.

TypeScript
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);}

Opsi

ParameterTipeDeskripsi
pagenumberNomor halaman (dimulai dari 1).
perPagenumberJumlah rekaman per halaman.

Menghasilkan payload connectionSuggestionsForAccount: records beserta pageInfo. Rekaman saran tidak memiliki field id. Pengenalnya adalah matchedDataDatabaseId, dan accountType (GMB, FB, atau APPLE) menunjukkan tipe rekaman hasil pencocokan tersebut. Simpan keduanya bersama-sama, karena confirmConnectedAccountMatches memerlukan keduanya untuk membentuk ID yang diterimanya. Akun yang belum memiliki hasil pencocokan mengembalikan array records kosong.

confirmConnectedAccountMatches

Terima pasangan yang telah ditinjau. Konfirmasi menautkan setiap lokasi ke profil bisnisnya pada platform publikasi sehingga pembaruan lokasi berikutnya dapat diteruskan.

Bentuk setiap ID dari rekaman saran: gabungkan nama tipe rekaman hasil pencocokan dan matchedDataDatabaseId rekaman dengan tanda titik dua, lalu kodekan hasilnya menggunakan base64. GMB dipetakan ke GmbLocationMatchedData, FB ke FbLocationMatchedData, dan APPLE ke AppleLocationMatchedData.

TypeScript
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);

Parameter

ParameterTipeDeskripsi
matchRecordIdsstring[]ID rekaman hasil pencocokan yang telah dikodekan untuk dikonfirmasi. Setidaknya satu ID wajib disertakan.

Menghasilkan payload confirmConnectMatches: success dan failedIds. Periksa success pada setiap pemanggilan: ID yang hasil dekodenya tidak sesuai dengan salah satu dari tiga tipe akan menghasilkan respons berformat keberhasilan dengan success bernilai false dan tanpa failedIds. Jika beberapa ID gagal, failedIds berisi ID basis data hasil dekode, bukan nilai yang telah dikodekan yang Anda kirim, jadi cocokkan kembali ID tersebut dengan matchedDataDatabaseId.

Menghubungkan satu profil bisnis ke satu lokasi

Tiga metode menyelesaikan penghubungan antara satu profil bisnis yang telah dicocokkan dan satu lokasi, dan didokumentasikan bersama endpoint profil bisnis lainnya agar tidak didokumentasikan dua kali:

Gunakan metode-metode ini setelah confirmConnectedAccountMatches menangani sebagian besar lokasi dalam suatu akun, saat masih ada satu gerai yang perlu dipasangkan secara manual.


oauthDisconnect

Operasi pemutusan koneksi untuk satu lokasi yang sama, yang diakses melalui jalur OAuth per lokasi. Operasi ini menerima argumen yang sama persis dan menghasilkan payload yang sama persis, jadi pilih nama yang lebih mudah dipahami dalam kode Anda.

TypeScript
await client.oauthDisconnect(1800289, 'GOOGLE');

Parameter

ParameterTipeDeskripsi
locationIdstring | numberLokasi yang akan diputus koneksinya.
sitestringPlatform publikasi yang koneksinya akan diputus: 'GOOGLE', 'FACEBOOK', atau 'APPLE'.

Menghasilkan payload disconnectConnectedAccountsLocations, dengan kunci yang sama seperti yang dikembalikan oleh disconnectListing.

disconnectGoogleAccount

Putuskan koneksi seluruh akun Google: setiap lokasi yang terhubung melalui akun tersebut berhenti menerima pembaruan. Gunakan metode ini saat pelanggan berhenti menggunakan layanan atau mengalihkan kepemilikan.

TypeScript
await client.disconnectGoogleAccount('4f712c17-4f95-42dd-90f4-97171a2e67b5');

Parameter

ParameterTipeDeskripsi
connectedAccountIdstringAkun Google yang akan diputus koneksinya.

Menghasilkan payload gmbBulkDisconnect, yang memuat success. Operasi ini berlaku untuk seluruh akun dan tidak dapat diterapkan sebagian: untuk memutus hubungan satu lokasi sambil mempertahankan akun, gunakan disconnectListing. Nilai true untuk success tetap dikembalikan meskipun ID tidak dikenal, jadi baca fetchConnectedAccounts setelahnya jika Anda memerlukan kepastian.

disconnectFacebookAccount

Operasi yang setara untuk Facebook, dengan argumen yang sama dan perilaku yang sama, yaitu berlaku untuk seluruh akun dan tidak dapat diterapkan sebagian.

TypeScript
await client.disconnectFacebookAccount('9d2b5a41-0c7e-4f83-bb16-2ac43e70d915');

Parameter

ParameterTipeDeskripsi
connectedAccountIdstringAkun Facebook yang akan diputus koneksinya.

Menghasilkan payload fbBulkDisconnect, yang memuat success. Hal yang sama perlu diperhatikan: ID yang tidak dikenal tetap dilaporkan berhasil, jadi verifikasi dengan fetchConnectedAccounts.

Alur kerja penyiapan awal yang umum

connect_google.ts
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');