Blog Ecommerce 8 min read

Magento 2 Product Image Placeholder for Missing SKUs

Override Magento 2's default no_selection placeholder with a generated URL and apply consistent image fallbacks in Luma, Hyvä, and PWA Studio frontends.

Magento placeholder imageMagento 2 product imageno_selection imageHyvä fallbackPWA Studio image
Magento 2 Product Image Placeholder for Missing SKUs

Magento 2 stores a special `no_selection` sentinel value in the product image database field when no image has been uploaded for a product. The core image helper translates this into a URL pointing to the configured placeholder image in the store admin. By default, that placeholder is a generic gray box.

Replacing `no_selection` products with dimension-matched, branded fallback URLs requires a small override at the template or data layer. The strategy differs between traditional Luma themes, Hyvä themes, and headless PWA Studio frontends, but the core check is the same: detect `no_selection` or a placeholder URL and substitute a generated one.

no_selection sentinel

How Magento 2 signals a missing product image

In Magento 2's `catalog_product_entity_varchar` table, the `no_selection` string is stored as the image attribute value for products without an uploaded image. The PHP `\Magento\Catalog\Block\Product\AbstractProduct::getImage()` method and the related `ProductImageFactory` check for this sentinel and fall back to the configured placeholder image stored in `pub/media/catalog/product/placeholder/`.

The admin-configured placeholder appears on every product grid, product page, and cart thumbnail where no real image exists. It is a single image across the entire catalog — there is no per-category or per-attribute variation without custom development.

The practical consequence is that large catalogs imported from an ERP or PIM system look visually identical for all SKUs that lacked images in the source system. Buyers cannot distinguish between similar products in search or category views.

Admin configuration

Override the default placeholder in Admin

The simplest approach is uploading a better placeholder to Stores > Configuration > Catalog > Product Image Placeholders. Upload separate images for Base Image, Small Image, and Thumbnail. This is a global change requiring no code deployment.

The limitation is that the same image appears for every product. If your catalog spans multiple categories, a generic 'Image Coming Soon' graphic is the best universal placeholder. For more targeted fallbacks — where the SKU name or category appears in the placeholder — a URL-based approach is necessary.

Luma theme

Template override for Luma themes

In Luma, product images are rendered through a complex block chain involving `Magento_Catalog::product/list/items.phtml`, view models, and image helpers. The cleanest override for the fallback is a custom theme override on the product image template that checks the resolved URL and replaces the admin-configured placeholder path with a generated one.

Check the URL against the known placeholder path prefix (`pub/media/catalog/product/placeholder/`) rather than the `no_selection` value, since you are working at the template render layer after the PHP helper has already resolved the value.

Implementation text
<?php
// app/design/frontend/Vendor/theme/Magento_Catalog/templates/product/image.phtml
/** @var \Magento\Catalog\Block\Product\Image $block */

$imageSrc = $block->getImageUrl();
$placeholderPattern = '/catalog/product/placeholder/';

if (strpos($imageSrc, $placeholderPattern) !== false || empty($imageSrc)) {
    $productName = urlencode($block->getLabel());
    $width = $block->getWidth() ?: 300;
    $height = $block->getHeight() ?: 300;
    $imageSrc = "https://fallback.pics/api/v1/{$width}x{$height}?text={$productName}";
}
?>
<img
  src="<?= $block->escapeUrl($imageSrc) ?>"
  alt="<?= $block->escapeHtmlAttr($block->getLabel()) ?>"
  width="<?= (int)$block->getWidth() ?>"
  height="<?= (int)$block->getHeight() ?>"
  loading="lazy"
/>

Hyvä theme

Alpine.js or Tailwind Hyvä theme approach

Hyvä themes use Alpine.js components and Tailwind CSS. Image rendering in Hyvä often goes through the `Hyva\Theme\ViewModel\ProductImages` view model or directly through product page JavaScript components. You can add an `onerror` attribute directly on the img tag to substitute the fallback URL when the placeholder image itself returns a 404.

Set the fallback URL in a PHP variable and output it into the Alpine data context or directly as the onerror attribute value. Avoid inline event handlers that reference unreachable variables.

Implementation text
<?php
$placeholderUrl = "https://fallback.pics/api/v1/{$width}x{$height}?text=" . urlencode($productName);
?>
<img
  src="<?= $escaper->escapeUrl($imageSrc) ?>"
  alt="<?= $escaper->escapeHtmlAttr($productName) ?>"
  width="<?= (int)$width ?>"
  height="<?= (int)$height ?>"
  onerror="this.src='<?= $escaper->escapeJs($placeholderUrl) ?>'; this.onerror=null;"
  loading="lazy"
/>

PWA Studio

React component fallback in PWA Studio

Magento PWA Studio uses Peregrine hooks to fetch product data and Venia UI components to render it. The `ProductImageComponent` in `@magento/venia-ui` accepts an `onError` prop. Pass a fallback URL generator that reads the product name and returns a dimension-matched placeholder URL.

PWA Studio queries product images via GraphQL. The `url_thumbnail`, `url_small_image`, and `url_full_size` fields on media gallery entries can each be null or point to the placeholder path. Check all three before concluding that no real image exists.

Implementation tsx
// src/components/ProductImage/productImage.js
import React, { useCallback, useState } from 'react';

const MAGENTO_PLACEHOLDER = '/media/catalog/product/placeholder/';

export function ProductImage({ src, name, width = 300, height = 300 }) {
  const fallback = `https://fallback.pics/api/v1/${width}x${height}?text=${encodeURIComponent(name)}`;
  const realSrc = src && !src.includes(MAGENTO_PLACEHOLDER) ? src : fallback;
  const [imgSrc, setImgSrc] = useState(realSrc);

  const handleError = useCallback(() => {
    setImgSrc(fallback);
  }, [fallback]);

  return (
    <img
      src={imgSrc}
      alt={name}
      width={width}
      height={height}
      onError={handleError}
      loading="lazy"
    />
  );
}

Resources

Further reading

For catalog image fallback strategies across ecommerce platforms, see the PrestaShop and BigCommerce guides.

Implementation text
https://fallback.pics/docs/
https://fallback.pics/placeholder-image-api/
https://fallback.pics/blog/prestashop-image-fallback/
https://fallback.pics/blog/bigcommerce-image-fallback/

Key takeaways

What to standardize before shipping

  • Magento 2 uses a no_selection sentinel and admin-configured placeholder images — detect the placeholder URL path to intercept it in templates.
  • Upload a better placeholder to Stores > Configuration > Catalog > Product Image Placeholders for the quickest global fix.
  • In Luma themes, override the product image template to check the resolved URL against the placeholder path prefix.
  • In Hyvä, use an onerror attribute with the PHP-generated fallback URL to handle both missing and broken images.
  • In PWA Studio, pass a fallback URL to the ProductImageComponent's onError prop and detect the Magento placeholder path on the src before render.

Production fallback layer

Use fallback.pics anywhere an image URL is accepted.

Start with one deterministic URL and standardize fallback behavior across your design system.

Read the docs