写真
listingsapi-js SDKを使って拠点にロゴ、カバー写真、ギャラリー写真を追加し、メイン画像にスターを付け、古いファイルを削除します。
写真は公開URLを使って拠点に添付します。画像を自分でホストすると、プラットフォームが取得して保存し、掲載先がそこから取得します。拠点にはロゴを1枚、カバーを1枚、追加の写真を任意の枚数保存でき、追加の写真のうち最大4枚にスターを付けられます。写真に関するすべてのメソッドはListingsAPIクライアントインスタンスにあり、拠点IDで対象を指定します。数値の拠点IDは自動的にエンコードされるため、1800289と'TG9jYXRpb246MTgwMDI4OQ=='はどちらも使用できます。
アップロードの成功には2つの形式があります。少量のバッチはその場で保存され、処理済みのメディアが返されます。大量のバッチはキューに登録され、ポーリング用のリクエストIDが返されます。画像数を自分で数えるのではなく、request.requestIdの有無で処理を分岐してください。
fetchLocationPhotos
拠点に添付されたすべてのメディアファイル(ロゴ、カバー、追加の画像)を一覧で取得します。アップロード前に呼び出して不足しているものを確認し、スターの設定と削除のメソッドに渡す写真IDを取得してください。
const photos = await client.fetchLocationPhotos(1800289); for (const p of photos) {console.log(p.id, p.categoryName, p.starred, p.url);}パラメータ
mediaFilesOfLocation配列に解決され、デフォルトは空の配列です。各ファイルにはid、url、thumbnailUrl、categoryName(Logo、Cover、またはAdditional)、categoryId、fileType、starred、viewsCountが含まれます。メディアのない拠点では空の配列が返されますが、これは作成直後の拠点では正常なレスポンスであり、エラーではありません。
addLocationPhotos
1枚以上の画像を拠点に添付します。各項目には、photoに公開アクセス可能なJPEGまたはPNGのURLを、typeに画像を配置する枠を指定する必要があります。
const result = await client.addLocationPhotos(1800289, [{ photo: 'https://cdn.example.com/brightsmile/logo.png', type: 'LOGO' },{ photo: 'https://cdn.example.com/brightsmile/storefront.jpg', type: 'ADDITIONAL' },]); if (result.request?.requestId) {// Queued: poll fetchPhotoUploadStatus with this idconsole.log('queued', result.request.requestId);} else {for (const p of result.photos ?? []) { console.log('stored', p.id, p.type);}}写真のオプション
パラメータ
success、photos、request、errors、clientMutationIdを含むaddLocationPhotosペイロードに解決されます。その場で処理されるアップロードでは、photosに新しいメディアが入り、各メディアにはid、databaseId、url、thumbnailUrl、type、starredが含まれ、requestは空のオブジェクトになります。キューに登録されるアップロードでは、photosが空になり、request.requestIdが設定されます。どちらも成功です。
画像はJPEGまたはPNGである必要があり、枠ごとに掲載先のサイズ規則が適用されます。拠点にはロゴとカバーをそれぞれ1枚だけ保存できるため、どちらも再アップロードすると既存の画像が置き換わります。typeは用途に合わせて設定してください。ギャラリー画像にはADDITIONALを指定します。
fetchPhotoUploadStatus
キューに登録されたアップロードの結果が確定するまでポーリングします。addLocationPhotosが返したrequest.requestIdを使用してください。
let job = await client.fetchPhotoUploadStatus('e6c2d9d9-9a18-4015-88cf-9a4e19a6f49a'); while (job.status === 'PROCESSING') {await new Promise((resolve) => setTimeout(resolve, 5000));job = await client.fetchPhotoUploadStatus('e6c2d9d9-9a18-4015-88cf-9a4e19a6f49a');} for (const p of job.photos ?? []) {if (p.status === 'ERROR') { console.log('rejected:', p.errorMessage);}}パラメータ
ペイロードには、requestId、PROCESSING、SUCCESS、ERRORのいずれかを値とするジョブのstatus、およびphotos配列が含まれ、配列の各要素にはmediaId、locationId、要素ごとのstatus、errorMessageが含まれます。
ジョブのstatusは処理の終了を示し、すべての画像が保存されたことを示すものではありません。SUCCESSのジョブにも拒否された写真が含まれることがあるため、PROCESSINGでなくなったらphotosを走査し、各要素を確認してください。ポーリングの間には数秒の待機時間を設けてください。間隔を空けずにループすると、すぐにレート制限に達します。有効期限が切れたIDでは結果が確定しないため、最近のアップロードで取得したIDだけをポーリングしてください。
starLocationPhotos
追加の写真にスターを付けると、注目画像に対応している掲載先で優先的に表示され、falseを渡すとスターを外せます。
// Feature a photoconst result = await client.starLocationPhotos(1800289,['TWVkaWFGaWxlOjU4Nzg5MzI='],true,); console.log(result.success, result.photos[0].starred); // Reverse itawait client.starLocationPhotos(1800289, ['TWVkaWFGaWxlOjU4Nzg5MzI='], false);パラメータ
starUnstarLocationPhotosペイロードに解決されます。これにはsuccess、photos、およびerrors配列ではなく単一のerrorオブジェクトが含まれます。返される各写真には、id、databaseId、url、thumbnailUrl、type、新しいstarredの値が含まれます。
スターを付けられるのはADDITIONALの写真だけで、ロゴとカバーはすでに優先表示の対象です。拠点に保存できるスター付きの写真は最大4枚で、チェック時にはすでにスターが付いている写真と今回の呼び出しで指定した写真の合計を数えるため、4枚を超えるとリクエスト全体が失敗します。
removeLocationPhotos
IDを指定して、写真を拠点から取り外します。古くなったギャラリー画像を削除したり、誤ったインポートを取り消したりするために使用します。
const result = await client.removeLocationPhotos(1800289, ['TWVkaWFGaWxlOjU4Nzg5MzI=',]); console.log(result.removedCount); // 1パラメータ
removedCount、errors、clientMutationIdを含むremoveLocationPhotosペイロードに解決されます。removedCountが0でerrorsがnullの場合、送信したIDの写真はどれもその拠点に添付されていなかったことを意味し、これによってすでに取り外されていたIDを検出できます。
ここで削除できるのはADDITIONALの写真だけです。ロゴやカバーを置き換えるには、新しい画像をアップロードしてください。メディアを削除すると拠点から取り外されますが、アカウントのメディアライブラリからファイルが完全に削除されるとは限りません。
一般的なギャラリーの更新
import { ListingsAPI } from 'listingsapi-js'; const client = new ListingsAPI(); // reads LISTINGSAPI_KEY from envconst LOCATION_ID = 1800289; // Brightsmile Dental // 1. See what is already attachedconst existing = await client.fetchLocationPhotos(LOCATION_ID);const hasLogo = existing.some((p) => p.categoryName === 'Logo'); // 2. Upload only what is missing, plus the new hero shotconst uploaded = await client.addLocationPhotos(LOCATION_ID, [...(hasLogo ? [] : [{ photo: 'https://cdn.example.com/brightsmile/logo.png', type: 'LOGO' as const }]),{ photo: 'https://cdn.example.com/brightsmile/hero-2026.jpg', type: 'ADDITIONAL' as const },]); // 3. Feature the new hero shotconst hero = (uploaded.photos ?? []).find((p) => p.type === 'ADDITIONAL');if (hero) {await client.starLocationPhotos(LOCATION_ID, [hero.id], true);} // 4. Retire last season's imagesconst stale = existing.filter((p) => p.categoryName === 'Additional' && !p.starred).map((p) => p.id);if (stale.length > 0) {const removed = await client.removeLocationPhotos(LOCATION_ID, stale);console.log('removed ' + removed.removedCount + ' stale photos');}関連リソース
- 拠点、拠点IDを調べます
- エラー処理、すべてのメソッドがスローする型付きエラー
- ロゴ、カバー、写真のアップロード、手順全体の解説
- RESTリファレンス: 写真の取得、写真のアップロード、一括アップロードのステータス、写真へのスターの付与、写真の削除