Setting the file. One moment.
Store Image · Wix Vibe Headless · wix/skills · Skills Docs
ContentsBack to the top of the page 22.10
Post Detail
Reference Use Variant Options
references/storefront/app/lib/ storeImage.js
JavaScript · 64 lines · 3 KB
!
url)
return
null
;
9 if (url. startsWith ( "//" )) return `https:${ url }` ;
10 return url;
11 }
12
13 // A Wix media id (e.g. "abc123~mv2.jpg") is NOT a URL — build the static CDN url for it.
14 export function wixMediaUrl ( mediaId ) {
15 if ( ! mediaId || typeof mediaId !== "string" ) return null ;
16 if (mediaId. startsWith ( "http" ) || mediaId. startsWith ( "//" )) return storeImage (mediaId);
17 return `https://static.wixstatic.com/media/${ mediaId }` ;
18 }
19
20 // The media id inside a Wix image url (…/media/<id>/v1/… or a bare …/media/<id>). Compare two urls of
21 // the SAME image that differ only in sizing/format params by their id, not full-string equality.
22 export function wixMediaId ( url ) {
23 const m = typeof url === "string" && url. match ( / \/ media \/ ( [ ^ /?] + )/ );
24 return m ? m[ 1 ] : url;
25 }
26
27 // The image assigned to a product OPTION CHOICE (e.g. a colour swatch). The storefront fetches with the
28 // PRODUCT_CHOICES_MEDIA_REFERENCES field, so Wix returns the choice image at choice.media.items[].mediaId
29 // and returns choice.linkedMedia EMPTY. Read media.items — do NOT switch this to choice.linkedMedia even
30 // if a direct admin/API probe shows linkedMedia populated: a probe made WITHOUT that field mask returns
31 // linkedMedia, but the storefront requests the mask, which blanks linkedMedia and returns media.items.
32 export function choiceImage ( choice ) {
33 const mediaId = choice?.media?.items?.[ 0 ]?.mediaId;
34 return mediaId ? wixMediaUrl (mediaId) : null ;
35 }
36
37 // The image for a resolved VARIANT (a full choice combination). Wix computes variant.media from the
38 // picked choices' media, so this is the exact image for the current selection — prefer it over a
39 // single choice's image once all options are chosen.
40 // ⚠️ Read `media.image.url` (the URL the API already returns), or build from `media.id` — the
41 // `~mv2` file id. NOT `media.uploadId`: that's a dashed GUID (the id the file was uploaded with),
42 // and https://static.wixstatic.com/media/<uploadId> is a 403. Variants without media (a fresh
43 // template's demo products) return null, and the caller falls back to the choice's own image.
44 export function variantImage ( variant ) {
45 const m = variant?.media;
46 if ( ! m) return null ;
47 return storeImage (m.image?.url) || wixMediaUrl (m.id) || storeImage (m.thumbnail?.url);
48 }
49
50 // The main catalog image for a product (grid tiles, cart fallbacks).
51 export function productImage ( product ) {
52 return storeImage (product?.media?.main?.image?.url);
53 }
54
55 // Every gallery image for a product, main first, de-duplicated — `media.itemsInfo.items` repeats the
56 // main image, and video items carry no `image.url`. Returns [{ url, altText }].
57 export function productGallery ( product ) {
58 const items = product?.media?.itemsInfo?.items || [];
59 const urls = [ productImage (product), ... items. map (( i ) => storeImage (i))];
60 const seen = new Set ();
61 return urls
62 . map (( url , i ) => ({ url, altText: items[i - 1 ]?.altText || product?.name || "" }))
63 . filter (({ url }) => url && ! seen. has (url) && seen. add (url));
64 }