الحسابات المتصلة

اربط حسابات Google وFacebook وApple Business Connect، وطابق إدراجات أنشطتها التجارية مع المواقع، وافصلها باستخدام SDK ‏listingsapi-js.

الحساب المتصل هو تفويض OAuth يمنحه مالك حساب Google Business Profile أو صفحات Facebook أو Apple Business Connect. بمجرد وجود التفويض، يمكن للمنصة قراءة إدراجات الأنشطة التجارية التي يملكها ذلك الحساب وربط كل منها بموقع. جميع دوال الحسابات المتصلة متاحة على كائن العميل ListingsAPI.

الترتيب المعتاد هو: إنشاء رابط اتصال، وانتظار منح المالك التفويض، وسرد الحسابات للحصول على connectedAccountId، وبدء المطابقة، ومراجعة الاقتراحات، ثم تأكيدها أو ربط إدراج نشاط تجاري يدويًا. تُرجع كل دالة عند اكتمالها البيانات الموجودة ضمن مفتاح الاستجابة الخاص بها، والمذكور في القسم المقابل أدناه.

connectGoogleAccount

أنشئ رابط OAuth على مستوى الحساب بالكامل لـ Google Business Profile. وجّه المالك إلى url المُرجع؛ وسيعود إلى successUrl أو errorUrl لديك عند إغلاق شاشة الموافقة.

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

المعاملات

المعاملالنوعالوصف
successUrlstringعنوان URL مطلق يعود إليه المالك بعد منح التفويض.
errorUrlstringعنوان URL مطلق يعود إليه المالك إذا ألغى العملية أو فشل التفويض.

تُرجع بيانات bulkConnectLinkForGoogle: url وsuccess وerrors. تحقّق من url ولا تكتفِ بـ success، لأن إعادة التوجيه غير القابلة للاستخدام قد تُرجع نتيجة نجاح مع قيمة null في url. مدة صلاحية الرابط قصيرة، لذا أنشئ رابطًا جديدًا لكل محاولة.

connectFacebookAccount

الدالة المقابلة لـ connectGoogleAccount في صفحات Facebook، وتقبل وسيطَي إعادة التوجيه نفسيهما.

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

المعاملات

المعاملالنوعالوصف
successUrlstringعنوان URL مطلق يعود إليه المالك بعد منح التفويض.
errorUrlstringعنوان URL مطلق يعود إليه المالك إذا ألغى العملية أو فشل التفويض.

تُرجع بيانات bulkConnectLinkForFacebook: url وsuccess وerrors.

getOauthConnectUrl

أنشئ رابط OAuth يقتصر نطاقه على موقع واحد بدلًا من حساب كامل. استخدمه عندما تعرف مسبقًا الموقع الذي يربطه المالك وتريد إعادته إلى شاشة ذلك الموقع في منتجك.

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

المعاملات

المعاملالنوعالوصف
locationIdstring | numberالموقع الذي يُربط به الاتصال. تُرمَّز المعرّفات الرقمية تلقائيًا.
sitestringمنصة النشر المراد الاتصال بها: 'GOOGLE' أو 'FACEBOOK' أو 'APPLE'.
successUrlstringعنوان URL مطلق يعود إليه المالك بعد منح التفويض.
errorUrlstringعنوان URL مطلق يعود إليه المالك إذا فشل التفويض.

تُرجع بيانات createConnectUrl: url وsuccess وerrors. عنوانا إعادة التوجيه مطلوبان ويجب أن يكونا مطلقين. الرابط صالح للاستخدام مرة واحدة ومرتبط بالموقع الذي حددته.

fetchConnectedAccounts

اسرد حسابات Google وFacebook المفوَّضة ضمن حسابك، مع حالة سلامة الاتصال وأعداد المواقع المرتبطة. من هنا تحصل على connectedAccountId الذي تحتاج إليه كل دالة لاحقة.

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

الخيارات

المعاملالنوعالوصف
publisherstringنوع الحساب، مثل 'GoogleAccount' أو 'FacebookAccount'.
statusstringعامل تصفية حالة الاتصال: 'Connected' أو 'NotConnected' أو 'ConnectionIssue'.
pagenumberرقم الصفحة (يبدأ من 1).
perPagenumberعدد السجلات لكل صفحة.

تُرجع بيانات connectedAccountsInfo: مصفوفة records بالإضافة إلى pageInfo الذي يتضمن hasNextPage وhasPreviousPage وtotalPages وtotalRecords. يحتوي كل سجل على connectedAccountId وemail وconnectedAccountType وconnectedLocationsCount وconnectivityIssue وstatus وrequestMatchesStatus.

لا يستخدم عامل التصفية والحقل مجموعة القيم نفسها. يقبل الخيار status القيم 'Connected' أو 'NotConnected' أو 'ConnectionIssue'، بينما تكون قيمة status في السجل نفسه هي CONNECTED أو MATCH_IN_PROGRESS أو CONNECTIVITY_ISSUE. يُرفض تمرير قيمة السجل بوصفها قيمة عامل التصفية.

fetchConnectedAccountDetails

اقرأ حسابًا واحدًا باستخدام معرّفه. هذه الدالة أقل تكلفة من تصفّح جميع صفحات القائمة عندما يكون المعرّف متاحًا لديك بالفعل، وهي الدالة التي تُستدعى دوريًا أثناء تشغيل المطابقة.

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

المعاملات

المعاملالنوعالوصف
connectedAccountIdstringمعرّف الحساب المتصل، المأخوذ من fetchConnectedAccounts.

تُرجع بيانات connectedAccountDetails، التي تتضمن السجل ضمن details بالحقول نفسها التي تُرجعها القائمة. راقب requestMatchesStatus لمعرفة متى تصبح الاقتراحات جاهزة، واقرأ status وconnectivityIssue لتحديد ما إذا كان ينبغي طلب إعادة التفويض.

fetchConnectedAccountFolders

اسرد مجموعات حساب Google (المجلدات) التي يمكن للحساب المتصل الوصول إليها. استدعِ هذه الدالة قبل createGmbListing عندما يريد المالك وضع إدراج النشاط التجاري الجديد في مجموعة محددة.

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

الخيارات

المعاملالنوعالوصف
folderNamestringاحصر النتيجة في المجلدات المطابقة لهذا الاسم.

تُرجع مصفوفة getFoldersUnderGoogleAccount، وتكون مصفوفة فارغة افتراضيًا. يحتوي كل مجلد على folderId (سلسلة نصية بصيغة accounts/<id> تمرّرها دون تغيير) وfolderName وlocationCount، الذي قد تكون قيمته null عندما لا يُبلغ Google عن عدد. هذا المسار صالح فقط للحسابات من نوع Google.

fetchConnectedAccountListings

اسرد إدراجات الأنشطة التجارية لدى منصات النشر التي يمكن للحساب المتصل الوصول إليها. قيمة id في كل سجل هي بالضبط قيمة connectedAccountListingId التي تقبلها connectListing، وبذلك يمكنك إنشاء واجهة لاختيار إدراج نشاط تجاري.

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

الخيارات

المعاملالنوعالوصف
locationInfostringبحث بنص حر في اسم النشاط التجاري والعنوان والمنطقة والرمز البريدي ورمز المتجر ورقم الهاتف.
pagenumberرقم الصفحة (يبدأ من 1).
perPagenumberعدد السجلات لكل صفحة. القيمة الافتراضية هي 500، وهي أيضًا الحد الأقصى.

تُرجع بيانات connectedAccountListings: records بالإضافة إلى pageInfo. يحتوي كل سجل على id وlocationName وaddress وphone وliveLink وaccountTypeName. رغم أن الطلب الأساسي يتخذ صيغة طلب كتابة، فهذه عملية قراءة: تضع SDK معرّف الحساب ومعاملات تقسيم النتائج إلى صفحات في جسم الطلب تلقائيًا، وفقًا لما تتطلبه نقطة النهاية.

triggerConnectedAccountMatches

أضف إلى قائمة الانتظار المهمة التي تجلب كل ملف تعريفي يمكن للحسابات المحددة الوصول إليه وتطابق هذه الملفات مع مواقعك. استدعِ هذه الدالة فور انتهاء المالك من شاشة الموافقة، ومرة أخرى بعد إنشاء المواقع دفعة واحدة.

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

المعاملات

المعاملالنوعالوصف
connectedAccountIdsstring[]الحسابات المطلوب تشغيل المطابقة لها.

تُرجع بيانات connectedAccountsTriggerMatches: success وfailedIds. تعني قيمة true في success أن المهمة أُضيفت إلى قائمة الانتظار، ولا تعني أن المطابقة اكتملت. استدعِ fetchConnectedAccountDetails دوريًا حتى تصبح قيمة requestMatchesStatus هي MATCH_COMPLETED، ثم اقرأ الاقتراحات.

fetchConnectionSuggestions

اقرأ أزواج المطابقة الناتجة، ليتمكن المشغّل من مقارنة كل موقع بإدراج النشاط التجاري لدى منصة النشر قبل إجراء أي ربط.

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

الخيارات

المعاملالنوعالوصف
pagenumberرقم الصفحة (يبدأ من 1).
perPagenumberعدد السجلات لكل صفحة.

تُرجع بيانات connectionSuggestionsForAccount: records بالإضافة إلى pageInfo. لا يحتوي سجل الاقتراح على حقل id. معرّفه هو matchedDataDatabaseId، ويحدد accountType (GMB أو FB أو APPLE) نوع سجل المطابقة. احتفظ بالقيمتين معًا، لأن confirmConnectedAccountMatches يحتاج إليهما لإنشاء المعرّف الذي يقبله. يُرجع الحساب الذي لا توجد له مطابقات بعد مصفوفة records فارغة.

confirmConnectedAccountMatches

اقبل أزواج المطابقة التي تمت مراجعتها. يربط التأكيد كل موقع بإدراج نشاطه التجاري لدى منصة النشر، بحيث تُطبَّق عليه تحديثات الموقع اللاحقة.

أنشئ كل معرّف من سجل اقتراح: صِل اسم نوع سجل المطابقة بقيمة matchedDataDatabaseId في السجل باستخدام نقطتين رأسيتين، ثم رمّز الناتج باستخدام base64. يقابل GMB النوع GmbLocationMatchedData، ويقابل FB النوع FbLocationMatchedData، ويقابل APPLE النوع 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);

المعاملات

المعاملالنوعالوصف
matchRecordIdsstring[]معرّفات سجلات المطابقة المرمَّزة المطلوب تأكيدها. يلزم معرّف واحد على الأقل.

تُرجع بيانات confirmConnectMatches: success وfailedIds. تحقّق من success في كل استدعاء: إذا لم ينتج عن فك ترميز المعرّف أحد الأنواع الثلاثة، تُرجع الدالة استجابة بصيغة استجابة نجاح، بقيمة false في success ودون failedIds. عند فشل بعض المعرّفات، يحتوي failedIds على معرّفات قاعدة البيانات بعد فك ترميزها، وليس على القيم المرمَّزة التي أرسلتها، لذا طابقها مع matchedDataDatabaseId.

ربط إدراج نشاط تجاري واحد بموقع واحد

تُكمل 3 طرق الربط بين إدراج نشاط تجاري واحد تمت مطابقته وموقع واحد، وهي موثّقة مع بقية نقاط نهاية إدراجات الأنشطة التجارية لتجنب تكرار توثيقها:

استخدم هذه الطرق بعد أن تعالج confirmConnectedAccountMatches معظم عناصر الحساب، إذا ظل هناك متجر واحد يحتاج إلى ربط يدوي.


oauthDisconnect

هذه هي عملية قطع الاتصال نفسها لموقع واحد، ويمكن الوصول إليها عبر مسار OAuth الخاص بكل موقع. تقبل الوسائط نفسها وتُرجع الحمولة نفسها، لذا اختر الاسم الأنسب في شيفرتك.

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

المعلمات

المعلمةالنوعالوصف
locationIdstring | numberالموقع المراد قطع اتصاله.
sitestringمنصة النشر المراد قطع الاتصال بها: 'GOOGLE' أو 'FACEBOOK' أو 'APPLE'.

تُرجع حمولة disconnectConnectedAccountsLocations، بالمفتاح نفسه الذي تُرجعه disconnectListing.

disconnectGoogleAccount

تقطع اتصال حساب Google بالكامل: يتوقف كل موقع مرتبط من خلاله عن تلقي التحديثات. استخدمها عندما يتوقف عميل عن استخدام الخدمة أو ينقل الملكية.

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

المعلمات

المعلمةالنوعالوصف
connectedAccountIdstringحساب Google المراد قطع اتصاله.

تُرجع حمولة gmbBulkDisconnect، التي تتضمن success. تشمل هذه العملية الحساب بالكامل ولا يمكن تطبيقها جزئيًا: لفك ربط موقع واحد مع الاحتفاظ بالحساب، استخدم disconnectListing. تُرجع success بقيمة true حتى إذا كان المعرّف غير معروف، لذا اقرأ fetchConnectedAccounts بعد ذلك إذا كنت بحاجة إلى التأكد.

disconnectFacebookAccount

الطريقة المقابلة لـ Facebook، وتقبل الوسيط نفسه وتنطبق على الحساب بالكامل بالطريقة نفسها دون إمكانية تطبيقها جزئيًا.

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

المعلمات

المعلمةالنوعالوصف
connectedAccountIdstringحساب Facebook المراد قطع اتصاله.

تُرجع حمولة fbBulkDisconnect، التي تتضمن success. ينطبق التحفظ نفسه: تُفيد العملية بالنجاح حتى إذا كان المعرّف غير معروف، لذا تحقّق باستخدام fetchConnectedAccounts.

سير عمل الإعداد الأولي المعتاد

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