게시물
listingsapi-js SDK로 Google과 Facebook에 공지, 이벤트, 혜택을 게시합니다.
게시물 메서드는 Google Business Profile과 Facebook에 콘텐츠를 게시하고, 사이트별 게시 상태와 분석 데이터를 확인할 수 있도록 합니다. 모든 게시물 메서드는 ListingsAPI 클라이언트 인스턴스에서 직접 사용할 수 있습니다.
게시는 비동기식으로 처리됩니다. 생성 호출은 status: 'INPROGRESS'을 반환하며, 게시물은 백그라운드에서 게시됩니다. 상태가 SUCCESS이 될 때까지 fetchPost을 폴링하고, publishDetails[].submissionError에서 사이트별 실패 내역을 확인합니다.
bulkPublish
한 번의 호출로 여러 사업장의 Google과 Facebook에 게시물 하나를 게시합니다. sites의 기본값은 두 사이트 모두입니다. 메시지 또는 사이트별 맵은 사이트당 하나의 항목으로 확장되고, 사업장 ID는 자동으로 인코딩되며, 네트워크 호출 전에 클라이언트 측에서 페이로드를 검증합니다(유효하지 않은 페이로드는 즉시 ValidationError을 발생시킵니다).
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(result.socialPost.id, result.socialPost.status); // INPROGRESS, publishes async사이트별 문구를 지정하려면 message에 객체를 전달합니다:
await client.bulkPublish({name: 'Holiday hours',locationIds: [16808, 16809],message: { GOOGLE: 'Open until 10pm through the holidays. Book online!', FACEBOOK: 'We are staying open late for the holidays. See you soon!',},});옵션
createAnnouncement
CTA와 미디어를 선택적으로 포함할 수 있는 일반 메시지인 ANNOUNCEMENT 게시물을 생성합니다. bulkPublish과 동일한 옵션을 받지만 postType과 contextInfo은 제외되며, 여기서 sites의 기본값은 ['GOOGLE']입니다.
await client.createAnnouncement({name: 'Grand Opening',locationIds: [16808],message: 'Acme Dental is now open in the Mission!',sites: ['GOOGLE'],ctaType: 'LEARN_MORE',ctaUrl: 'https://example.com/opening',});createEvent
제목과 시작 및 종료 기간이 있는 EVENT 게시물을 생성합니다. title은 필수이며(Google에서 요구합니다), startDay과 endDay은 YYYY-MM-DD 형식의 날짜이고, startTime/endTime은 선택적으로 지정할 수 있는 표시용 시간입니다. sites의 기본값은 ['GOOGLE']입니다.
await client.createEvent({name: 'Live music',locationIds: [16808],message: 'Join us Friday for live jazz!',title: 'Jazz Night',startDay: '2026-08-01',endDay: '2026-08-01',startTime: '7:00pm',endTime: '10:00pm',});createOffer
쿠폰, 할인 및 약관이 포함된 OFFER 게시물을 생성합니다. title은 필수이며, 다른 모든 혜택 필드는 선택 사항입니다. sites의 기본값은 ['GOOGLE']입니다.
await client.createOffer({name: 'Summer sale',locationIds: [16808],message: '20% off whitening all week!',title: 'Summer Sale',couponCode: 'SUMMER20',discount: '20%',redeemUrl: 'https://example.com/sale',termsConditions: 'One per customer.',startDay: '2026-08-01',endDay: '2026-08-07',});혜택 옵션
createPost
클라이언트 측 검증 없이, 중첩되지 않은 필드로 구성된 원시 본문으로 게시물을 생성합니다. 이 메서드는 전달된 내용을 API에서 요구하는 input 객체로 감싸므로 실제 전송 본문은 {"input": {...}}이 되며, 중첩 구조가 전혀 없는 본문은 HTTP 400으로 거부됩니다. 이 본문을 구성하고 검증하는 createAnnouncement, createEvent 또는 createOffer을 우선 사용합니다.
await client.createPost({postName: 'Grand Opening',locationIds: ['TG9jYXRpb246MTY4MDg='],postType: 'ANNOUNCEMENT',postSites: ['GOOGLE'],postMessage: [{ site: 'GOOGLE', message: 'We are now open!' }],});fetchPost
게시물의 콘텐츠, 사이트별 게시 상태 및 분석 데이터를 조회합니다. INPROGRESS 게시물이 게시될 때까지 폴링하는 데 사용합니다.
let post = await client.fetchPost('U29jaWFsUG9zdDo0NDEyMg=='); while (post.status === 'INPROGRESS') {await new Promise((resolve) => setTimeout(resolve, 5000));post = await client.fetchPost('U29jaWFsUG9zdDo0NDEyMg==');} for (const detail of post.publishDetails ?? []) {if (detail.submissionError) { console.log('failed:', detail.submissionError);}}deletePost
게시물을 삭제하고, 해당 게시물이 게시된 모든 사이트에서 제거합니다.
await client.deletePost('U29jaWFsUG9zdDo0NDEyMg==');fetchLocationPosts
특정 사업장을 대상으로 하는 게시물 캠페인 목록을 조회합니다. 오프셋 페이지네이션(page 및 perPage)을 사용하며, 비동기 작업이 완료되면 postsByLocation을 반환합니다.
이 경로는 tag을 거부하므로, SDK는 0.3.2부터 하위 호환성을 위해 이 옵션을 받지만 실제 요청에는 절대 포함하지 않습니다. 태그 필터링이 필요하면 fetchLocationBulkPosts을 사용합니다.
const posts = await client.fetchLocationPosts(16808, { page: 1, perPage: 10 });옵션
fetchBulkPost
사업장별 게시 상태 및 분석 데이터와 함께 일괄 캠페인을 조회합니다.
const bulk = await client.fetchBulkPost('QnVsa1Bvc3Q6OTk=');fetchLocationBulkPosts
특정 사업장이 포함된 일괄(여러 사업장 대상) 캠페인 목록을 조회합니다. fetchLocationPosts과 동일한 옵션을 받습니다.
const campaigns = await client.fetchLocationBulkPosts(16808, { page: 1, perPage: 10 });