Optimization Guide

Shopify ImageObject Schema for Visual Search — Product Image Structured Data & AI Vision Markup

Google Lens processes over 12 billion visual searches per month. AI shopping agents with vision capabilities — including GPT-4o, Gemini, and Claude — index product images to answer queries like "find me a lamp that looks like this" or "where can I buy the jacket worn in this photo." Shopify's default JSON-LD outputs product images as bare URL strings, discarding alt text, dimensions, primary-image signals, and gallery structure. Upgrading to full ImageObject markup is the single highest-leverage visual-search optimization for Shopify merchants.

TL;DR Replace the bare string "image": "https://cdn.shopify.com/…jpg" with a full ImageObject block: include contentUrl, description (mapped from alt text), width, height, encodingFormat, and representativeOfPage: true on the primary image. Use an array of ImageObject values for multi-image galleries. Map product.images[i].alt to the description field — Shopify's default output silently drops alt text from JSON-LD. Add thumbnail for hover-preview-optimized versions.

Why Product Images Are Invisible to AI Visual Search Without Schema

Visual search AI systems index products in two steps: (1) crawl the image URL to analyze the visual content, and (2) read the structured data on the page to understand what the image represents. Without structured data, a crawler seeing "image": "https://cdn.shopify.com/s/files/1/0001/myproduct.jpg" gets only the image URL — no description, no context about whether it's the primary product shot or a packaging detail, no alt text, no dimensions. The AI must infer everything from the pixel content alone, which is error-prone for product imagery (multiple angles, lifestyle context, similar-looking SKUs).

Full ImageObject markup solves this by providing machine-readable metadata alongside the visual content. Google's systems use representativeOfPage to select which image to show in Shopping tiles. AI shopping agents use description to understand what is shown in each image before fetching it. Image search ranking algorithms use width/height aspect ratio and encodingFormat to match images to query contexts (portrait for apparel, square for products, widescreen for lifestyle).

ImageObject property reference

Property Type Visual search use Example
contentUrl URL Primary crawlable image URL (CDN link) https://cdn.shopify.com/…/product.jpg
url URL Canonical page URL where the image lives — use product URL https://example.com/products/navy-wool-coat
description Text Alt text — AI semantic understanding of image content Navy double-breasted wool coat, front view
caption Text Editorial caption — additional context beyond alt text Available in navy, camel, and forest green
representativeOfPage Boolean Designates the primary product image for Shopping tiles true (primary only)
width QuantitativeValue or Integer Pixel width — aspect ratio signal for format matching 1200
height QuantitativeValue or Integer Pixel height — aspect ratio signal 1600
encodingFormat Text (MIME type) Image format — WebP preferred for performance signals image/webp
thumbnail ImageObject Smaller preview version — used in rich snippets + social cards 400px version of the same image

Primary Image Pattern: Single ImageObject on Product

For the simplest case — a product with one primary image — replace the bare string image URL with a full ImageObject. Set representativeOfPage: true to designate it as the page's primary visual. Map the Shopify image alt text to description.

Default Shopify — bare string
{
  "@type": "Product",
  "name": "Navy Wool Coat",
  "image": "https://cdn.shopify.com/
    s/files/1/0001/coat.jpg"
  // No alt text
  // No dimensions
  // No primary signal
  // AI infers everything from pixels
}
Full ImageObject — AI-ready
{
  "@type": "Product",
  "name": "Navy Wool Coat",
  "image": {
    "@type": "ImageObject",
    "contentUrl": "https://cdn.../coat.jpg",
    "description": "Navy wool coat,
      front view on white bg",
    "representativeOfPage": true,
    "width": 1200,
    "height": 1600,
    "encodingFormat": "image/jpeg"
  }
}

Multi-Image Gallery: ImageObject Array

When a product has multiple images (multiple angles, lifestyle shots, detail views), output them as an array under the Product's image property. Set representativeOfPage: true only on the primary image — usually the main white-background hero shot.

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Product",
  "name": "Navy Double-Breasted Wool Coat",
  "description": "Tailored double-breasted coat in 100% virgin wool. Notched lapels, two front welt pockets, fully lined. Available in sizes XS–3XL.",
  "sku": "COAT-NAVY-DB-WOOL",
  "brand": { "@type": "Brand", "name": "Archibald & Co." },
  "image": [
    {
      "@type": "ImageObject",
      "contentUrl": "https://cdn.shopify.com/s/files/1/0001/coat-front.jpg",
      "url": "https://example.com/products/navy-wool-coat",
      "description": "Navy double-breasted wool coat, front view, white background — Archibald & Co.",
      "representativeOfPage": true,
      "width": 1200,
      "height": 1600,
      "encodingFormat": "image/jpeg",
      "thumbnail": {
        "@type": "ImageObject",
        "contentUrl": "https://cdn.shopify.com/s/files/1/0001/coat-front_400x.jpg",
        "width": 400,
        "height": 533,
        "encodingFormat": "image/jpeg"
      }
    },
    {
      "@type": "ImageObject",
      "contentUrl": "https://cdn.shopify.com/s/files/1/0001/coat-back.jpg",
      "url": "https://example.com/products/navy-wool-coat",
      "description": "Navy double-breasted wool coat, back view showing single center vent and half-belt detail",
      "representativeOfPage": false,
      "width": 1200,
      "height": 1600,
      "encodingFormat": "image/jpeg"
    },
    {
      "@type": "ImageObject",
      "contentUrl": "https://cdn.shopify.com/s/files/1/0001/coat-detail-lapel.jpg",
      "url": "https://example.com/products/navy-wool-coat",
      "description": "Close-up detail of notched lapel and top button on navy wool coat",
      "representativeOfPage": false,
      "width": 800,
      "height": 800,
      "encodingFormat": "image/jpeg"
    },
    {
      "@type": "ImageObject",
      "contentUrl": "https://cdn.shopify.com/s/files/1/0001/coat-lifestyle.jpg",
      "url": "https://example.com/products/navy-wool-coat",
      "description": "Model wearing navy wool coat over cream turtleneck and dark trousers, city street setting",
      "caption": "Styled with Archibald & Co. merino turtleneck",
      "representativeOfPage": false,
      "width": 1200,
      "height": 1500,
      "encodingFormat": "image/jpeg"
    }
  ]
}
</script>

The caption property on lifestyle images provides additional editorial context — AI agents use it to understand styling relationships between products. For the lifestyle shot above, the caption signals that the coat is styled with a turtleneck, which can influence "complete the look" AI shopping recommendations.

Alt Text in JSON-LD: The Shopify Gap

Shopify's Dawn theme and most popular themes render product JSON-LD from the product.json object, which includes only the image URL — not the alt text you've painstakingly entered in the Shopify admin (Products → Edit → Images → Add alt text). This is a significant gap: Google's image indexing systems and AI vision agents use the description field in ImageObject as the primary text signal for understanding image content in the absence of on-page context.

The fix is straightforward in Liquid: the product.images[i].alt property exposes the admin-entered alt text. Map it to the description field in your ImageObject JSON-LD block. If no alt text has been entered, fall back to the product title concatenated with a positional description ("Product image 2 of 4").

Alt text quality signals for AI visual search

Alt text quality Example AI visual search impact
Poor image1.jpg (filename only) Zero semantic signal; AI relies entirely on pixel analysis
Basic Navy coat Color + product type — minimal for disambiguation
Good Navy double-breasted wool coat, front view Color, material, style, angle — strong product-level signal
Optimal Navy double-breasted 100% virgin wool coat by Archibald & Co., front view on white background, sizes XS–3XL Includes brand, material composition, size range — AI can match "wool coats XS size" visual queries

Dawn Liquid Snippet: Full ImageObject Output

Save as snippets/product-image-schema.liquid and render from your product template via {% raw %}{% render 'product-image-schema' %}{% endraw %}. The snippet iterates all product images, outputs a full ImageObject for each, sets representativeOfPage: true on the first, and falls back to a clean description string if no alt text is present.

{% comment %} product-image-schema.liquid — full ImageObject JSON-LD for all product images {% endcomment %}
{% assign primary_image = product.featured_image %}
{% assign all_images = product.images %}

{% if all_images.size > 0 %}
<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Product",
  "name": {{ product.title | json }},
  "url": "{{ shop.url }}{{ product.url }}",
  "image": [
    {% for image in all_images %}
    {% assign is_primary = false %}
    {% if image.id == primary_image.id %}{% assign is_primary = true %}{% endif %}

    {% assign img_alt = image.alt %}
    {% if img_alt == blank %}
      {% assign img_alt = product.title | append: ' — product image ' | append: forloop.index | append: ' of ' | append: all_images.size %}
    {% endif %}

    {% assign img_url = image | img_url: '1200x' %}
    {% assign thumb_url = image | img_url: '400x' %}
    {% assign img_format = 'image/jpeg' %}
    {% if image.src contains '.webp' %}{% assign img_format = 'image/webp' %}{% endif %}
    {% if image.src contains '.png' %}{% assign img_format = 'image/png' %}{% endif %}

    {
      "@type": "ImageObject",
      "contentUrl": "https:{{ img_url }}",
      "url": "{{ shop.url }}{{ product.url }}",
      "description": {{ img_alt | json }},
      "representativeOfPage": {{ is_primary }},
      "encodingFormat": {{ img_format | json }},
      "thumbnail": {
        "@type": "ImageObject",
        "contentUrl": "https:{{ thumb_url }}",
        "encodingFormat": {{ img_format | json }}
      }
    }{% unless forloop.last %},{% endunless %}
    {% endfor %}
  ]
}
</script>
{% endif %}

This snippet outputs the image array as a standalone Product JSON-LD block. To merge it with your existing product JSON-LD, extract just the "image": [...] array and splice it into your main product schema block. The standalone approach is safer for most themes as it avoids JSON-LD conflicts.

ImageGallery for Editorial Collections

For editorial lookbook pages or collection pages that feature multiple products in context, use ImageGallery — an ItemList of ImageObject values. This schema type signals to AI that the page is a curated image collection rather than a single product page, enabling AI shopping agents to identify and surface individual products from within the gallery.

{
  "@context": "https://schema.org",
  "@type": "ImageGallery",
  "name": "Spring 2026 Collection — Lookbook",
  "description": "Styled product photography for the Archibald & Co. Spring 2026 outerwear collection.",
  "url": "https://example.com/collections/spring-2026",
  "image": [
    {
      "@type": "ImageObject",
      "contentUrl": "https://cdn.shopify.com/…/lookbook-01.jpg",
      "description": "Model in navy wool coat and camel trousers, rooftop setting",
      "about": {
        "@type": "Product",
        "name": "Navy Wool Coat",
        "url": "https://example.com/products/navy-wool-coat"
      }
    },
    {
      "@type": "ImageObject",
      "contentUrl": "https://cdn.shopify.com/…/lookbook-02.jpg",
      "description": "Model in camel cashmere overcoat, park setting",
      "about": {
        "@type": "Product",
        "name": "Camel Cashmere Overcoat",
        "url": "https://example.com/products/camel-cashmere-overcoat"
      }
    }
  ]
}

The about property on each ImageObject in the gallery links the image to the specific product it depicts. AI shopping agents use this to serve "shop the look" recommendations — when a user uploads a photo of a coat they saw in a lookbook, the AI can trace the image back to the product via this structured link.

Shopify Metafield Architecture for Image SEO

Metafield key Type Maps to Notes
seo.image_caption Multi-line text ImageObject.caption (primary image) Editorial caption for lifestyle/hero image
seo.image_license URL ImageObject.license Optional: points to usage rights page (for wholesale/press kits)
seo.primary_image_width Integer ImageObject.width Override for width when CDN transformation changes dimensions
seo.primary_image_height Integer ImageObject.height Override for height

Note: Shopify Liquid's img_url filter applies size transformations (e.g., image | img_url: '1200x'), which changes the rendered image dimensions from the original. If your product images are uploaded at 2000×2000 and you serve them at 1200×, output "width": 1200 in the ImageObject, not 2000. The dimensions should match the contentUrl you're pointing to, not the original upload dimensions.

5 Common ImageObject Mistakes in Shopify

# Mistake Impact Fix
1 Bare string image URL instead of ImageObject No alt text, no dimensions, no primary signal, no encoding format — AI visual search operates blind on your images Upgrade to full ImageObject block with contentUrl, description, representativeOfPage, width, height, encodingFormat
2 Alt text entered in Shopify admin but not mapped to JSON-LD description Google structured data crawler and AI indexers don't read HTML alt attributes from JSON-LD context — the admin alt text you wrote is silently invisible to machine indexing Explicitly map image.alt to ImageObject.description in the Liquid snippet
3 Multiple images all with representativeOfPage: true Search systems receive conflicting primary-image signals and fall back to algorithmic selection — often choosing a lifestyle shot or detail image over the primary white-background hero shot for Shopping tiles Set representativeOfPage: true only on the primary product image (product.featured_image). All other images: omit or set false
4 CDN transformation URL dimensions don't match stated width/height Search quality systems flag dimension mismatches as data quality errors. A 2000px wide image served at 1200px via img_url: '1200x' should state width: 1200, not 2000 Always output dimensions matching the transformed URL, not the original upload dimensions
5 Generic filenames and no alt text on non-primary images Secondary images (back views, detail shots, lifestyle) without alt text contribute zero semantic signal to visual search — AI cannot disambiguate product-back from product-front, or identify styling context Write descriptive alt text for all images in the Shopify admin. Use format: "[Color] [Product type], [view/angle description]" — e.g., "Navy wool coat, back view showing single vent"

Frequently Asked Questions

Why does Shopify's default JSON-LD fail for visual search?

Shopify outputs images as bare URL strings — "image": "https://cdn.shopify.com/…/product.jpg" — which discards alt text, dimensions, primary-image designation, and encoding format. AI visual search crawlers and Google Lens need the full ImageObject block to understand what each image depicts without fetching and analyzing every pixel. See Shopify Product Image Alt Text & AI Agents for broader alt text optimization guidance.

What is representativeOfPage and why does it matter?

Set representativeOfPage: true on the primary product image to tell Google's image systems which image to use in Shopping tiles, image carousels, and AI shopping agent product cards. Without this signal, systems guess — and frequently pick a lifestyle or detail shot over the clean hero image. Only one ImageObject per product page should carry representativeOfPage: true.

How does alt text in JSON-LD differ from the HTML alt attribute?

The HTML alt attribute is for screen readers and browser fallback. The ImageObject.description in JSON-LD is what Google's structured data crawler ingests for semantic image indexing. Shopify's default output doesn't bridge these — your carefully-written admin alt text is invisible to structured data crawlers unless you explicitly map it. The Liquid snippet above does this via image.alt.

Should I use 'image' as a string URL or as an ImageObject?

Always prefer the full ImageObject form. Schema.org allows both, but the full object unlocks: representativeOfPage, description (alt text), width/height (aspect ratio), encodingFormat, and thumbnail. For multiple images, "image" accepts an array of ImageObject values. See Shopify Product Images & AI Shopping Agents for broader image optimization strategy.

How do I handle variant-specific images in ImageObject schema?

Use an array of all product images in the Product's image property for the simplest implementation. For variant-specific image linking, add an image property to each Offer object pointing to the variant-specific ImageObject. This tells AI agents which image corresponds to which variant (e.g., a blue variant's Offer links to the blue colorway ImageObject). For full variant schema, see Shopify ProductGroup & Variant Schema.

Are your product images invisible to AI visual search?

CatalogScan audits your Shopify store's structured data and identifies bare-string image URLs, missing alt text in JSON-LD, absent representativeOfPage signals, and ImageObject gaps across your entire catalog.

Run Free Scan

Related Resources