Kullanım senaryoları

listingsapi-js kaynaklarının gerçek entegrasyonlarda nasıl birleştirileceğini gösteren uçtan uca TypeScript örnekleri.

Bu örnekler, tek bir metot sayfasının yeterli olmadığı durumlarda kullanabileceğiniz, birden fazla kaynağı kapsayan iş akışlarıdır. Her biri, iki veya daha fazla kaynağı bir araya getiren ve üretim ortamında kullanabileceğiniz eksiksiz, çalıştırılabilir bir TypeScript programıdır. Sürümü sabitlenmiş bir SDK yükleyin (npm install listingsapi-js@0.3.2), kontrol panelinizden aldığınız bir anahtarla LISTINGSAPI_KEY ortam değişkenini dışa aktarın; ardından bu programları npx tsx <file>.ts ile olduğu gibi çalıştırabilirsiniz.

SDK'yı ilk kez kullanıyorsanız önce Node SDK genel bakış sayfasını okuyun. Bu sayfa, aşağıdaki her örneğin bildiğinizi varsaydığı istemci oluşturma, kimlik doğrulama, hatalar ve sayfalama konularını kapsar.

1. Hızlı başlangıç: konumları getirme ve yazdırma

En temel entegrasyon: kimlik doğrulaması yapın, bir sayfa konum alın ve adlarını yazdırın.

01_quickstart.ts
import { ListingsAPI } from 'listingsapi-js'; const client = new ListingsAPI(); // reads LISTINGSAPI_KEY from env const page = await client.fetchAllLocations({ first: 5 });if (!Array.isArray(page)) {for (const loc of page.locations) {  console.log(loc.name + ' - ' + loc.city);}}

fetchAll olmadan fetchAllLocations, locations, pageInfo ve raw verilerini içeren bir nesne döndürür. Sonraki sayfayı almak için pageInfo.endCursor değerini after olarak iletin.

2. JSON biçiminde toplu dışa aktarma

Hesaptaki tüm konumları otomatik sayfalama ile alın ve sonuçları diske yazın.

02_bulk_export.ts
import { writeFileSync } from 'fs';import { ListingsAPI } from 'listingsapi-js';import type { Location } from 'listingsapi-js'; const client = new ListingsAPI(); const locations = (await client.fetchAllLocations({fetchAll: true,pageSize: 100,})) as Location[]; writeFileSync('locations.json', JSON.stringify(locations, null, 2));console.log('Exported ' + locations.length + ' locations to locations.json');

fetchAll: true, cursor tabanlı sayfaları otomatik olarak takip eder ve düz bir Location[] döndürür. 10 000'den fazla konum için, tek tek isteklerin hızlı kalması amacıyla pageSize değerini varsayılan değer olan 100 olarak tutun.

3. Yeni bir konum oluşturma

fetchSubcategories ile doğru kategori kimliğini bulun, ardından konumu oluşturun. createLocation, subCategoryId olarak bir alt kategorinin databaseId değerini bekler. API ayrıca en az 200 karakterlik bir açıklama gerektirir.

03_onboarding.ts
import { ListingsAPI } from 'listingsapi-js'; const client = new ListingsAPI(); const categories = await client.fetchSubcategories();const dentist = categories.find((c) => c.name === 'Dentist');if (!dentist) throw new Error('Category not found'); const description ='Acme Dental is a family-owned dental practice in downtown New York ' +'offering preventive care, cosmetic dentistry, orthodontics, and ' +'emergency appointments. Our team has served the neighborhood for over ' +'twenty years with same-week scheduling and weekend hours.'; const created = await client.createLocation({name:          'Acme Dental',storeId:       'ACME-NY-001',street:        '123 Jump Street',city:          'New York',stateIso:      'NY',postalCode:    '10013',countryIso:    'US',phone:         '6443859313',subCategoryId: dentist.databaseId,description:   description,}); console.log('Created location', created.location?.id);

Doğrulama başarısız olduğunda (eksik alan, kısa açıklama, geçersiz kategori), platformun hata kayıtlarını err.errors üzerinde içeren bir ValidationError fırlatılır; dolayısıyla kontrol edilecek bir success bayrağı yoktur.

4. Google ve Facebook'ta toplu gönderi yayımlama

bulkPublish, tek bir çağrıyla birçok konum için her iki sitede de aynı gönderiyi yayımlar. İstek verilerini istemci tarafında doğrular, mesajı her site için ayrı ayrı oluşturur ve sayısal konum kimliklerini sizin için kodlar.

04_bulk_publish.ts
import { ListingsAPI } from 'listingsapi-js'; const client = new ListingsAPI(); const result = await client.bulkPublish({name:        'Holiday hours',locationIds: [16808, 16809, 16810],message:     'Open until 10pm through the holidays!',mediaUrl:    'https://cdn.example.com/holiday.jpg',ctaType:     'LEARN_MORE',ctaUrl:      'https://example.com/holiday-hours',}); console.log('Campaign:', result.socialPost?.id, result.socialPost?.status); // Publishing is asynchronous; poll the bulk campaign for per-location statusconst bulk = await client.fetchBulkPost(result.socialPost.id);console.log(bulk);

sites için varsayılan değer ['GOOGLE', 'FACEBOOK'] olur. Metnin farklı olması gerektiğinde, message olarak site bazında bir eşleme iletin ({ GOOGLE: '...', FACEBOOK: '...' }). Türleri tanımlanmış seçeneklerle tek tek kampanyalar oluşturmak için bunun yerine createAnnouncement, createEvent veya createOffer kullanın.

5. Yorum takibi: düşük puanları işaretleme

Her konumda 1 ve 2 yıldızlı yorumları tarayın ve ilgilenilmesi gerekenleri günlüğe kaydedin.

05_review_monitoring.ts
import { ListingsAPI, APIError } from 'listingsapi-js';import type { Interaction, Location } from 'listingsapi-js'; const client = new ListingsAPI(); const locations = (await client.fetchAllLocations({ fetchAll: true })) as Location[]; for (const loc of locations) {let reviews: Interaction[];try {  reviews = (await client.fetchInteractions(loc.id, {    fetchAll:      true,    startDate:     '2026-01-01',    ratingFilters: [1, 2],  })) as Interaction[];} catch (err) {  if (err instanceof APIError) {    console.error(loc.name + ': ' + err.statusCode);    continue;  }  throw err;} for (const review of reviews) {  const who = review.reviewerName ?? 'Anonymous';  console.log('NEEDS ATTENTION [' + loc.name + '] ' + who + ' (' + review.rating + ' stars)');}}

6. Yanıtlanmamış yorumları yanıtlama

Henüz yanıtlanmamış her yorumu otomatik olarak yanıtlayın. Bir şablon kullanın veya buildResponse yerine bir LLM çağrısı kullanın.

06_bulk_respond.ts
import { ListingsAPI } from 'listingsapi-js';import type { Interaction } from 'listingsapi-js'; const client = new ListingsAPI();const LOCATION_ID = 16808; function buildResponse(review: Interaction): string {const name = review.reviewerName ?? 'there';if ((review.rating ?? 5) <= 2) {  return 'Hi ' + name + ', we are sorry to hear about your experience. Our team will reach out shortly.';}return 'Hi ' + name + ', thank you for the kind words. We look forward to seeing you again!';} const reviews = (await client.fetchInteractions(LOCATION_ID, {fetchAll:  true,startDate: '2026-01-01',})) as Interaction[]; let responded = 0;for (const review of reviews) {if (review.responses && review.responses.length > 0) continue;await client.respondToReview(review.id, buildResponse(review));responded++;}console.log('Responded to ' + responded + ' reviews');

7. Analiz raporu: Google, Bing, Facebook ve yorum istatistikleri

Tek bir konum için profil analizlerini ve yorum istatistiklerini paralel olarak alın ve tek sayfalık bir özet yazdırın.

07_analytics_report.ts
import { ListingsAPI } from 'listingsapi-js'; const client = new ListingsAPI();const LOCATION_ID = 16808;const range = { fromDate: '2026-01-01', toDate: '2026-06-30' }; const [google, bing, facebook, reviewOverview] = await Promise.all([client.fetchGoogleAnalytics(LOCATION_ID, range),client.fetchBingAnalytics(LOCATION_ID, range),client.fetchFacebookAnalytics(LOCATION_ID, range),client.fetchReviewAnalyticsOverview(LOCATION_ID, {  startDate: range.fromDate,  endDate:   range.toDate,}),]); console.log('Google insights:',  JSON.stringify(google));console.log('Bing insights:',    JSON.stringify(bing));console.log('Facebook insights:', JSON.stringify(facebook));console.log('Review overview:',  JSON.stringify(reviewOverview));

Parametre farkına dikkat edin: platform analizleri fromDate/toDate parametrelerini alırken yorum analizleri startDate/endDate parametrelerini alır.

8. İşletme kaydı denetimi: senkronize olmayan ve yinelenen profilleri bulma

Bir konumdaki senkronize olmayan premium işletme kayıtlarını ve ListingsAPI'nin bulduğu yinelenen profilleri tarayın, ardından yinelenenleri işaretleyin.

08_listings_audit.ts
import { ListingsAPI } from 'listingsapi-js'; const client = new ListingsAPI();const LOCATION_ID = 16808; const [premium, voice, duplicates] = await Promise.all([client.fetchPremiumListings(LOCATION_ID),client.fetchVoiceListings(LOCATION_ID),client.fetchDuplicateListings(LOCATION_ID),]); for (const l of premium) {if (l.syncStatus !== 'SYNCED') {  console.log('Not synced: ' + l.site + ' - ' + l.syncStatus);}} console.log('Voice listings: ' + voice.length);console.log('Duplicates detected: ' + duplicates.length); const ids = duplicates.map((d) => d.id).filter((id): id is string => typeof id === 'string'); if (ids.length > 0) {await client.markListingsAsDuplicate(LOCATION_ID, ids);console.log('Marked ' + ids.length + ' listings as duplicate');}

Hesap genelinde bir tarama için fetchAllDuplicateListings({ page: 1 }), tüm konumlardaki yinelenen kayıtların toplu bir özetini döndürür.

9. Bağlı hesaplar: Google iş akışı

Bir Google hesabını bir kez bağlayın, bu hesaptaki işletme kayıtlarını konumlarınızla eşleştirin ve önerilen eşleşmeleri onaylayın.

09_connected_accounts.ts
import { ListingsAPI } from 'listingsapi-js'; const client = new ListingsAPI(); // 1. Get an OAuth URL and send the account owner thereconst connect = await client.connectGoogleAccount('https://example.com/connected','https://example.com/connect-error',);console.log('Send the owner to:', JSON.stringify(connect)); // 2. After the owner completes OAuth, list connected accountsconst accounts = await client.fetchConnectedAccounts({ page: 1, perPage: 25 });console.log(JSON.stringify(accounts)); // 3. Trigger matching between the account's listings and your locationsconst accountId = 'connected-account-uuid';await client.triggerConnectedAccountMatches([accountId]); const suggestions = await client.fetchConnectionSuggestions(accountId, {page: 1,perPage: 25,});console.log(JSON.stringify(suggestions)); // 4. Confirm the matches you agree withawait client.confirmConnectedAccountMatches(['match-record-id-1','match-record-id-2',]);console.log('Matches confirmed');

Bunun yerine tek bir konumu bağlamak için getOauthConnectUrl(locationId, 'GOOGLE', successUrl, errorUrl), tek bir işletme kaydını doğrudan bağlamak için ise connectListing(locationId, listingId, accountId) kullanın.

10. Konum arama ve bir alanı toplu güncelleme

Bir sorguyla eşleşen konumları arayın, ardından her sonuçtaki bir alanı güncelleyin; örneğin, bir şehirdeki tüm konumlara yeni bir telefon numarası uygulayın.

10_bulk_update.ts
import { ListingsAPI } from 'listingsapi-js';import type { Location } from 'listingsapi-js'; const client = new ListingsAPI(); const matches = (await client.searchLocations('Brooklyn', { fetchAll: true })) as Location[]; let updated = 0;for (const loc of matches) {await client.updateLocation({  id:    loc.id,  phone: '7185550100',});updated++;}console.log('Updated phone on ' + updated + ' Brooklyn locations');

Sonraki adımlar

  • Konumlar: parametre tablolarıyla birlikte eksiksiz metot başvuru kaynağı
  • Yorumlar: analizler, ayarlar, ifade analizi
  • İşletme kayıtları: premium, sesli arama, yinelenen kayıtlar
  • Analizler: Google, Bing, Facebook istatistikleri
  • Hata işleme: APIError alt sınıfları ve yeniden deneme stratejisi