Anwendungsfälle

Vollständige TypeScript-Beispiele zeigen, wie Sie Ressourcen von listingsapi-js zu konkreten Integrationen kombinieren.

Diese Beispiele zeigen ressourcenübergreifende Abläufe – Skripte für Aufgaben, bei denen eine einzelne Methodenseite nicht ausreicht. Jedes Beispiel ist ein vollständiges, ausführbares TypeScript-Programm, das zwei oder mehr Ressourcen für einen praktisch einsetzbaren Anwendungsfall kombiniert. Installieren Sie eine festgelegte SDK-Version (npm install listingsapi-js@0.3.2), exportieren Sie LISTINGSAPI_KEY mit einem Schlüssel aus Ihrem Dashboard, und führen Sie die Programme unverändert mit npx tsx <file>.ts aus.

Wenn Sie das SDK noch nicht kennen, lesen Sie zuerst die Übersicht zum Node SDK. Sie behandelt die Erstellung des Clients, Authentifizierung, Fehler und Paginierung – Kenntnisse, die alle folgenden Beispiele voraussetzen.

1. Schnellstart: Standorte abrufen und ausgeben

Eine minimale Integration: authentifizieren, eine Seite mit Standorten abrufen und deren Namen ausgeben.

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

Ohne fetchAll gibt fetchAllLocations ein Objekt mit locations, pageInfo und den Nutzdaten in raw zurück. Übergeben Sie pageInfo.endCursor als after, um die nächste Seite abzurufen.

2. Massenexport nach JSON

Rufen Sie mithilfe automatischer Paginierung alle Standorte im Konto ab und speichern Sie die Ergebnisse auf dem Datenträger.

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 ruft die über Cursor verknüpften Seiten automatisch ab und gibt ein flaches Location[] zurück. Lassen Sie bei 10 000 oder mehr Standorten pageSize auf 100 (dem Standardwert), damit einzelne Anfragen schnell bleiben.

3. Einen neuen Standort einrichten

Ermitteln Sie mit fetchSubcategories die passende Kategorie-ID und erstellen Sie dann den Standort. createLocation erwartet als subCategoryId den Wert von databaseId einer Unterkategorie. Die API erfordert außerdem eine Beschreibung mit mindestens 200 Zeichen.

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

Bei einem Validierungsfehler (fehlendes Feld, zu kurze Beschreibung, ungültige Kategorie) wird ein ValidationError ausgelöst, dessen err.errors die Fehlereinträge der Plattform enthält; es gibt daher kein success-Flag, das Sie prüfen könnten.

4. Einen Beitrag für viele Standorte gleichzeitig auf Google und Facebook veröffentlichen

bulkPublish veröffentlicht mit einem einzigen Aufruf einen Beitrag für viele Standorte auf beiden Plattformen. Es validiert die Nutzdaten auf der Clientseite, bereitet die Nachricht für jede Plattform auf und kodiert numerische Standort-IDs für Sie.

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 verwendet standardmäßig ['GOOGLE', 'FACEBOOK']. Übergeben Sie als message eine Zuordnung pro Plattform ({ GOOGLE: '...', FACEBOOK: '...' }), wenn sich der Text unterscheiden soll. Verwenden Sie für einzelne Kampagnen mit typisierten Optionen stattdessen createAnnouncement, createEvent oder createOffer.

5. Bewertungen überwachen: niedrige Bewertungen kennzeichnen

Durchsuchen Sie jeden Standort nach Bewertungen mit 1 oder 2 Sternen und protokollieren Sie diejenigen, die Aufmerksamkeit erfordern.

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. Unbeantwortete Bewertungen beantworten

Beantworten Sie automatisch jede Bewertung, die noch keine Antwort hat. Verwenden Sie eine Vorlage oder ersetzen Sie buildResponse durch einen LLM-Aufruf.

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. Analysebericht: Google, Bing, Facebook und Bewertungsstatistiken

Rufen Sie Profilanalysen und Bewertungsstatistiken für einen einzelnen Standort parallel ab und geben Sie eine einseitige Zusammenfassung aus.

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

Beachten Sie die unterschiedlichen Parameter: Plattformanalysen verwenden fromDate/toDate, während Bewertungsanalysen startDate/endDate verwenden.

8. Einträge prüfen: nicht synchronisierte und doppelte Profile finden

Prüfen Sie einen Standort auf nicht synchronisierte Premium-Einträge und auf doppelte Profile, die ListingsAPI gefunden hat, und markieren Sie anschließend die Duplikate.

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

Für eine kontoweite Prüfung gibt fetchAllDuplicateListings({ page: 1 }) eine Zusammenfassung der Duplikate über alle Standorte hinweg zurück.

9. Verbundene Konten: der Ablauf für Google

Verbinden Sie ein Google-Konto einmalig, ordnen Sie dessen Einträge Ihren Standorten zu und bestätigen Sie die vorgeschlagenen Zuordnungen.

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

Um stattdessen einen einzelnen Standort zu verbinden, verwenden Sie getOauthConnectUrl(locationId, 'GOOGLE', successUrl, errorUrl) und anschließend connectListing(locationId, listingId, accountId), um einen Eintrag direkt zu verknüpfen.

10. Standorte suchen und ein Feld für mehrere Standorte gleichzeitig aktualisieren

Suchen Sie nach Standorten, die einer Suchanfrage entsprechen, und aktualisieren Sie dann bei jedem Ergebnis ein Feld, beispielsweise um eine neue Telefonnummer für alle Standorte einer Stadt zu hinterlegen.

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

Weiterführende Informationen

  • Standorte: vollständige Methodenreferenz mit Parametertabellen
  • Bewertungen: Analysen, Einstellungen, Phrasenanalyse
  • Einträge: Premium, Sprachsuche, Duplikate
  • Analysen: Statistiken zu Google, Bing und Facebook
  • Fehlerbehandlung: Unterklassen von APIError und Strategie für Wiederholungsversuche