Displaying blog posts on the product card

Topic summary

A developer is working on displaying blog posts on product cards in Shopify and wants to implement a fallback system: if product-specific metafields contain blog post links, use those; otherwise, display globally assigned blog posts.

Current Setup:

  • Uses a single template that globally displays blog posts for all products
  • Has existing code that loops through blogs and articles to find and render two posts
  • Already created metafields (related_product_with_blog_post) storing two blog post links per product

Solution Provided:
A community member suggested simplifying the complex existing code by:

  • Storing comma-separated article links in metafields
  • Parsing these in Liquid (rather than JavaScript)
  • Iterating over the metafield links using a for loop
  • Extracting blog and article handles by splitting the URLs
  • Rendering each article using the blog-card snippet with proper parameters

Code Approach:
The solution involves splitting metafield URLs by /blogs/ to extract handles, then using Liquid objects to pull specific articles and render them with {% render "blog-card" %}. This method avoids performance issues from overly complex logic and provides cleaner conditional rendering based on metafield presence.

Summarized with AI on November 23. AI used: claude-sonnet-4-5-20250929.

Now blogs are displayed like this, i.e. globally for all products because I have created 1 template. I would like to create metafields to throw 2 links from each product and call them as blog entries.
How to replace it so that when the metafields were completed, it would take entries from them, and if not, globally?

{% liquid 
  assign firstArticleToRender = nil
  assign firstBlogHandle = nil
  assign secondArticleToRender = nil
  assign secondBlogHandle = nil
  assign articlesCounter = 0
%}

  {% for blogPage in section.settings.all_blogs.links %}
    {% if articlesCounter == 2 %}{% break %}{% endif %}
    {% for articleItem in blogs[blogHandle].articles %}
      {% if articlesCounter == 2 %}{% break %}{% endif %}
      {% if articleItem.handle == articleHandle %}
      {% if firstArticleToRender == nil %}
        {% liquid
          assign firstArticleToRender = articleItem 
          assign firstBlogHandle = blogHandle
        %}
      {% else %}
        {% liquid
          assign secondArticleToRender = articleItem
          assign secondBlogHandle = blogHandle
        %}
      {% endif %}
      {% endif %}
      {% assign articlesCounter = articlesCounter | plus: 1 %}
    {% endfor %}
  {% endfor %}

<div class="blog-section page-width">
  <div class="blog-section__description-container">
    <div class="blog-section__icon">
      {% if section.settings.select == "svg" %}
        {% if section.settings.svg_code != blank %}
          <div class="blog-section__image">
            {{ section.settings.svg_code }}
          </div>
        {% endif %}
      {% elsif section.settings.select == "img" %}
        {% if section.settings.image != blank %}
          <img class="blog-section__image"
            srcset="{% if section.settings.image.width >= 80 %}{{ section.settings.image | image_url: width: 80 }} 80w,{% endif %}
            {% if section.settings.image.width >= 100 %}{{ section.settings.image | image_url: width: 100 }} 100w,{% endif %}
            {% if section.settings.image.width >= 150 %}{{ section.settings.image | image_url: width: 150 }} 150w,{% endif %}
            {{ section.settings.image | image_url }} {{ section.settings.image.width }}w"
            alt="{{ section.settings.image.alt | escape }}"
            src="{{ section.settings.image | image_url }}"
            loading="lazy" />
        {% endif %}
      {% endif %}
    </div>
    {% if section.settings.header != nil %}
      <div class="blog-section__header">{{ section.settings.header | replace: '<', '<' | replace: '>', '>' | replace: '&nbsp;', ' ' }}</div>
    {% endif %}
    {% if section.settings.description != nil %}
      <p class="blog-section__paragraph">{{ section.settings.description }}</p>
    {% endif %}
  </div>
  <div class="blog-section__blog-card-container">
    {%- liquid 
      assign firstArticleHandle = section.settings.first_article | split: '/'
      assign secondArticleHandle = section.settings.second_article | split: '/'
    -%}
  
      {% render "card-blog", article: firstArticleToRender, blog_title: blogs[firstBlogHandle].title, blog_url: blogs[firstBlogHandle].url %}
      {% render "card-blog", article: secondArticleToRender, blog_title: blogs[secondBlogHandle].title, blog_url: blogs[secondBlogHandle].url %}
    {% if firstArticleHandle != blank and secondArticleHandle != blank %}
      {% render "card-blog", article: section.settings.first_article, blog_title: firstArticleHandle.first, blog_url: firstArticleHandle.first | prepend: '/blogs/' %}
      {% render "card-blog", article: section.settings.second_article, blog_title: secondArticleHandle.first, blog_url: secondArticleHandle.first | prepend: '/blogs/' %}
    {% elsif firstArticleHandle != blank or secondArticleHandle != blank %}
      {% if firstArticleHandle != blank %}
        {% render "card-blog", article: section.settings.first_article, blog_title: firstArticleHandle.first, blog_url: firstArticleHandle.first | prepend: '/blogs/' %}
      {% endif %}
      {% render "card-blog", article: firstArticleToRender, blog_title: blogs[firstBlogHandle].title, blog_url: blogs[firstBlogHandle].url %}
      {% if secondArticleHandle != blank %}
        {% render "card-blog", article: section.settings.second_article, blog_title: secondArticleHandle.first, blog_url: secondArticleHandle.first | prepend: '/blogs/' %}
      {% endif %}
    {% else %}
      {% if firstArticleToRender != nil %}
        {% render "card-blog", article: firstArticleToRender, blog_title: blogs[firstBlogHandle].title, blog_url: blogs[firstBlogHandle].url %}
      {% endif %}
      {% if secondArticleToRender != nil %}
        {% render "card-blog", article: secondArticleToRender, blog_title: blogs[secondBlogHandle].title, blog_url: blogs[secondBlogHandle].url %}
      {% endif %}
    {% endif %}
  </div>
  
  {% if section.settings.button_link != nil and section.settings.button_label != nil %}
    <a
      href="{{ section.settings.button_link }}"
      class="blog-section__button btn
        {% if section.settings.select_button_style == "primary1" %}
        btn--primary-1
        {% elsif section.settings.select_button_style == "primary2" %}
        btn--primary-2
        {% elsif section.settings.select_button_style == "secondary1" %}
        btn--secondary-1
        {% elsif section.settings.select_button_style == "secondary2" %}
        btn--secondary-2
        {% elsif section.settings.select_button_style == "underline" %}
        btn--tetrary-1
        {% endif %}
      ">
      {{ section.settings.button_label }}
    </a>
  {% endif %}
</div>

It looks like you are using very complex solution to achieve this, and it will affect store performance as well. You can just create a metafield and add comma separated articles list there and parse it in liquid. It will simplify the process.

If it is helpful to you, please give me a thumbs up as recognition and also mark it as the solution if applicable.
Thanks!

I already have 2 links in metafields that I display like this and I get 2 links but how to replace them in blog post rendering

If it is list then you should first convert into json to use in javascript like
let relatedLinks = {{ product.metafields.custom.related_product_with_blog_post | json }};

ok, I have the links pulled out, what next? is there any way to link them to blogs?

Do you need them on javascript ?
and what is stored in link here ?
you can just iterate over those links and use aricles liquid object to pull particular article

{% for related_product_with_blog_post_link in product.metafields.custom.related_product_with_blog_post.value %}
{% assign articleHandle = related_product_with_blog_post_link | split: “/blogs/” | last %}
{% assign blogHandleParts = articleHandle | split :“/” %}
{% assign blogHandle = blogHandleParts | first %}
{% assign _blog = blogs[blogHandle] %}
{% assign _article = articles[articleHandle] %}

{% render “card-blog”, article: _article, blog_title: _blog.title, blog_url: related_product_with_blog_post_link %}

{% endfor %}

1 Like