게시물

listingsapi-js SDK로 Google과 Facebook에 공지, 이벤트, 혜택을 게시합니다.

게시물 메서드는 Google Business Profile과 Facebook에 콘텐츠를 게시하고, 사이트별 게시 상태와 분석 데이터를 확인할 수 있도록 합니다. 모든 게시물 메서드는 ListingsAPI 클라이언트 인스턴스에서 직접 사용할 수 있습니다.

게시는 비동기식으로 처리됩니다. 생성 호출은 status: 'INPROGRESS'을 반환하며, 게시물은 백그라운드에서 게시됩니다. 상태가 SUCCESS이 될 때까지 fetchPost을 폴링하고, publishDetails[].submissionError에서 사이트별 실패 내역을 확인합니다.

bulkPublish

한 번의 호출로 여러 사업장의 Google과 Facebook에 게시물 하나를 게시합니다. sites의 기본값은 두 사이트 모두입니다. 메시지 또는 사이트별 맵은 사이트당 하나의 항목으로 확장되고, 사업장 ID는 자동으로 인코딩되며, 네트워크 호출 전에 클라이언트 측에서 페이로드를 검증합니다(유효하지 않은 페이로드는 즉시 ValidationError을 발생시킵니다).

TypeScript
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에 객체를 전달합니다:

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

옵션

매개변수유형설명
namestring내부 캠페인 이름입니다(고객에게 표시되지 않습니다). 필수입니다.
locationIdsArray<string | number>게시할 사업장입니다(숫자 또는 base64 ID). 필수입니다.
messagestring 또는 사이트별 맵모든 사이트에 사용할 게시물 본문 또는 { GOOGLE, FACEBOOK } 맵입니다. 필수입니다.
sitesPostSite[]대상 사이트입니다. 기본값은 ['GOOGLE', 'FACEBOOK']입니다.
postTypePostTypeANNOUNCEMENT(기본값), EVENT, OFFER, COVID19 또는 PRODUCT입니다.
ctaTypePostCtaTypeBOOK, ORDER, SHOP, LEARN_MORE, SIGN_UP 또는 GET_OFFER입니다. ctaUrl이 필요합니다.
ctaUrlstringCTA 버튼의 연결 대상입니다. ctaType이 필요합니다.
mediaUrlstring모든 사이트에 첨부할 공개 이미지 URL입니다.
scheduledDatesobject게시 및 만료 예약에 사용할 { startDatetime, endDatetime, removalSites }입니다.
contextInfoobjectpostType에서 요구하는 경우 제공할 이벤트 또는 혜택 세부 정보입니다.
additionalFieldsobject요청 본문에 그대로 병합할 추가 camelCase 필드이며, 중첩되지 않은 구조입니다.

createAnnouncement

CTA와 미디어를 선택적으로 포함할 수 있는 일반 메시지인 ANNOUNCEMENT 게시물을 생성합니다. bulkPublish과 동일한 옵션을 받지만 postType과 contextInfo은 제외되며, 여기서 sites의 기본값은 ['GOOGLE']입니다.

TypeScript
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']입니다.

TypeScript
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']입니다.

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

혜택 옵션

매개변수유형설명
titlestring혜택 제목입니다. 필수입니다.
couponCodestring고객이 혜택을 받기 위해 사용하는 코드입니다.
discountstring할인 설명입니다. 예: '20%'.
redeemUrlstring온라인에서 혜택을 사용할 수 있는 링크입니다.
termsConditionsstring이용 약관 텍스트입니다.
startDaystring혜택 유효 기간의 시작일이며, YYYY-MM-DD 형식입니다.
endDaystring혜택 유효 기간의 종료일이며, YYYY-MM-DD 형식입니다.

createPost

클라이언트 측 검증 없이, 중첩되지 않은 필드로 구성된 원시 본문으로 게시물을 생성합니다. 이 메서드는 전달된 내용을 API에서 요구하는 input 객체로 감싸므로 실제 전송 본문은 {"input": {...}}이 되며, 중첩 구조가 전혀 없는 본문은 HTTP 400으로 거부됩니다. 이 본문을 구성하고 검증하는 createAnnouncement, createEvent 또는 createOffer을 우선 사용합니다.

TypeScript
await client.createPost({postName: 'Grand Opening',locationIds: ['TG9jYXRpb246MTY4MDg='],postType: 'ANNOUNCEMENT',postSites: ['GOOGLE'],postMessage: [{ site: 'GOOGLE', message: 'We are now open!' }],});

fetchPost

게시물의 콘텐츠, 사이트별 게시 상태 및 분석 데이터를 조회합니다. INPROGRESS 게시물이 게시될 때까지 폴링하는 데 사용합니다.

TypeScript
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

게시물을 삭제하고, 해당 게시물이 게시된 모든 사이트에서 제거합니다.

TypeScript
await client.deletePost('U29jaWFsUG9zdDo0NDEyMg==');

fetchLocationPosts

특정 사업장을 대상으로 하는 게시물 캠페인 목록을 조회합니다. 오프셋 페이지네이션(page 및 perPage)을 사용하며, 비동기 작업이 완료되면 postsByLocation을 반환합니다.

이 경로는 tag을 거부하므로, SDK는 0.3.2부터 하위 호환성을 위해 이 옵션을 받지만 실제 요청에는 절대 포함하지 않습니다. 태그 필터링이 필요하면 fetchLocationBulkPosts을 사용합니다.

TypeScript
const posts = await client.fetchLocationPosts(16808, { page: 1, perPage: 10 });

옵션

매개변수유형설명
tagstring이 경로에서는 옵션을 받지만 전송하지 않습니다. 위의 참고 사항을 참조합니다.
pagenumber페이지 번호입니다(1부터 시작).
perPagenumber페이지당 결과 수입니다.
filtersobject게시물 필터 필드입니다(자동으로 JSON 인코딩됩니다).
sortFieldsobject{ field: 'created_at', order: 'Descending' }과 같은 정렬 객체입니다.

fetchBulkPost

사업장별 게시 상태 및 분석 데이터와 함께 일괄 캠페인을 조회합니다.

TypeScript
const bulk = await client.fetchBulkPost('QnVsa1Bvc3Q6OTk=');

fetchLocationBulkPosts

특정 사업장이 포함된 일괄(여러 사업장 대상) 캠페인 목록을 조회합니다. fetchLocationPosts과 동일한 옵션을 받습니다.

TypeScript
const campaigns = await client.fetchLocationBulkPosts(16808, { page: 1, perPage: 10 });