Blog CMS Workflows 7 min read

HubSpot CMS Default Featured Image Fallback Pattern

Set a reliable HubSpot CMS featured image fallback for blog posts and landing pages using HubL conditionals and a generated fallback URL.

HubSpot featured image fallbackHubSpot CMSHubL templateCMS WorkflowsBlog placeholder
HubSpot CMS Default Featured Image Fallback Pattern

HubSpot blog posts have a Featured Image field that is entirely optional. When posts are published without one, templates that reference `content.featured_image` receive an empty string. Using that empty string as an img src renders the broken-image browser icon and produces an empty `<img>` tag in the page source that search crawlers index.

HubL provides a straightforward conditional operator to substitute a fallback URL when the featured image is absent. Pair that with a generated fallback.pics URL and every post has a valid, cacheable image — whether or not the author uploaded one.

HubL template

Insert a fallback URL with a HubL conditional

Use HubL's `|default` filter or a straightforward `{% if %}` block to check for the empty string and substitute a fallback. The filter approach is more concise for inline use inside an `src` attribute.

Set `width` and `height` attributes on the `<img>` tag using the same dimensions as the fallback URL. This is critical for preventing layout shift when the image loads.

Implementation text
{# Blog post featured image with fallback #}
{% set fallback_image = "https://fallback.pics/api/v1/1200x630?text=" ~ content.name | urlencode %}

<img
  src="{{ content.featured_image | default(fallback_image) }}"
  alt="{{ content.featured_image_alt_text | default(content.name) }}"
  width="1200"
  height="630"
  loading="lazy"
/>

{# Short form using the default filter inline #}
<meta property="og:image"
  content="{{ content.featured_image | default(fallback_image) }}" />

Blog listing

Apply fallbacks in the blog listing template

The blog post listing template (`blog_listing.html`) iterates over `content_group.blog_listing_items`. Each item has its own `featured_image` field. Apply the fallback per item so every card in the listing has a visible image.

Use the post name (title) as the fallback text parameter for each card. This makes the generated placeholder informative and distinct for each post in the listing — editors can immediately see which posts still need images uploaded.

Implementation text
{% for item in content_group.blog_listing_items %}
  {% set fb = "https://fallback.pics/api/v1/600x400?text=" ~ item.name | urlencode %}
  <article class="blog-card">
    <a href="{{ item.absolute_url }}">
      <img
        src="{{ item.featured_image | default(fb) }}"
        alt="{{ item.featured_image_alt_text | default(item.name) }}"
        width="600"
        height="400"
        loading="lazy"
      />
    </a>
    <h2>{{ item.name }}</h2>
  </article>
{% endfor %}

Open Graph

Ensure social sharing always has an image

Social platforms pull the `og:image` meta tag when a URL is shared. An empty `og:image` means the shared post appears without a preview image on LinkedIn, Twitter/X, and Slack. Adding the fallback URL to the meta tag ensures every post gets a preview image even before the author uploads one.

The 1200×630 dimension is the standard for Open Graph images. Use the blog post title as the text parameter to make the generated social card informative. Authors can replace it with a custom image at any time — the fallback only activates when the field is empty.

Implementation text
<head>
  {% set og_image = content.featured_image
    | default("https://fallback.pics/api/v1/1200x630?text=" ~ content.name | urlencode) %}

  <meta property="og:image" content="{{ og_image }}" />
  <meta property="og:image:width" content="1200" />
  <meta property="og:image:height" content="630" />
  <meta name="twitter:image" content="{{ og_image }}" />
</head>

Landing pages

Module-level image fallbacks

HubSpot Landing Page modules have custom image fields defined in `module.html` and `meta.json`. You can set a default value in `meta.json` using the `default` property on the image field. This is the most robust approach for landing pages: the module always has a valid image value in the editor, and authors see a fallback in the live preview without any template logic.

For blog templates, the module default approach does not apply because `featured_image` is a built-in field. The HubL conditional in the template is required there.

Resources

Further reading

The fallback.pics thumbnail route generates blog-card-style images with a title, label, and gradient. It is a step up from the basic dimension placeholder when you want the fallback to look like an intentional design rather than a filler.

Implementation text
https://fallback.pics/docs/
https://fallback.pics/placeholder-image-api/
https://fallback.pics/blog/generate-blog-thumbnails-from-text/
https://fallback.pics/blog/og-image-placeholders-blogs-docs-social-sharing/

Key takeaways

What to standardize before shipping

  • HubSpot featured_image resolves to an empty string, not null — use the HubL | default filter or {% if %} block to substitute a fallback.
  • Include the post name in the fallback URL text parameter so each placeholder is identifiable in the listing.
  • Apply the same fallback to og:image and twitter:image meta tags so social shares always have a preview.
  • Match fallback dimensions to the slot dimensions — 1200×630 for Open Graph, 600×400 for listing cards.
  • Use module meta.json default values for custom landing page modules to avoid per-template conditional logic.

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