Hi! One type of blog post that we create are a list of color palettes that link out to products. We do this seasonally. I don’t want to flood our collections list with numerous new product collections each time this happens. My solution and question is how to display a metafield product list on the front end. The images below in sequence show 1) the created metafield 2) the metafield populated in the blog post on the back end, and 3) the desire location and orientation of this product list on the front end. The metafield does not come up as a viable metafield on the page. Any thoughts? As a note: tested a single product metafield and that populates just fine. Multiple products don’t. Thank you for your time!
Hello @ambullseye
Shopify doesn’t automatically render product list metafields on blog posts, which is why a single product metafield shows up but multiple ones don’t. To display them, you’ll need to manually loop through the metafield in your blog template using Liquid.
Hi @ambullseye
Yeah, the issue is that the Horizon theme does not have a section with an input type of product list. All are mostly using collections.
Recently, I answered a question on metaobject
But to copy just part, you need, maybe it helps.
The next part is a bit tricky, it depends on your theme. I used Horizon here and I used the Generate section. Because you have list of products, there should be in section product list input option. And not a collection like it is in most sections.
Open your theme editor, click on blocks, then click on new file icon. Enter name like city-product-list.liquid (mine was AI-generated so I had ai_gen_block_ab0f621.liquid, but you should be able to name it however you want) and enter this code:
{% assign ai_gen_id = block.id | replace: '_', '' | downcase %}
{% style %}
.ai-metaobject-carousel-{{ ai_gen_id }} {
position: relative;
width: 100%;
padding: {{ block.settings.section_padding }}px 0;
background-color: {{ block.settings.background_color }};
}
.ai-metaobject-carousel__container-{{ ai_gen_id }} {
max-width: 1200px;
margin: 0 auto;
padding: 0 20px;
}
.ai-metaobject-carousel__header-{{ ai_gen_id }} {
text-align: {{ block.settings.heading_alignment }};
margin-bottom: 30px;
}
.ai-metaobject-carousel__heading-{{ ai_gen_id }} {
margin: 0;
color: {{ block.settings.heading_color }};
font-size: {{ block.settings.heading_size }}px;
}
.ai-metaobject-carousel__wrapper-{{ ai_gen_id }} {
position: relative;
overflow: hidden;
}
.ai-metaobject-carousel__track-{{ ai_gen_id }} {
display: flex;
gap: {{ block.settings.gap }}px;
transition: transform 0.5s ease;
}
.ai-metaobject-carousel__slide-{{ ai_gen_id }} {
flex: 0 0 calc((100% - ({{ block.settings.products_per_row }} - 1) * {{ block.settings.gap }}px) / {{ block.settings.products_per_row }});
min-width: 0;
}
@media screen and (max-width: 749px) {
.ai-metaobject-carousel__slide-{{ ai_gen_id }} {
flex: 0 0 calc((100% - ({{ block.settings.products_per_row_mobile }} - 1) * {{ block.settings.gap }}px) / {{ block.settings.products_per_row_mobile }});
}
}
.ai-metaobject-carousel__product-card-{{ ai_gen_id }} {
background-color: {{ block.settings.card_background_color }};
border-radius: {{ block.settings.card_border_radius }}px;
overflow: hidden;
height: 100%;
display: flex;
flex-direction: column;
border: {{ block.settings.card_border_width }}px solid {{ block.settings.card_border_color }};
}
.ai-metaobject-carousel__product-image-{{ ai_gen_id }} {
position: relative;
width: 100%;
padding-bottom: 100%;
overflow: hidden;
background-color: #f5f5f5;
}
.ai-metaobject-carousel__product-image-{{ ai_gen_id }} img {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: cover;
}
.ai-metaobject-carousel__product-image-placeholder-{{ ai_gen_id }} {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
background-color: #f5f5f5;
}
.ai-metaobject-carousel__product-image-placeholder-{{ ai_gen_id }} svg {
width: 60%;
height: 60%;
opacity: 0.3;
}
.ai-metaobject-carousel__product-info-{{ ai_gen_id }} {
padding: 15px;
flex-grow: 1;
display: flex;
flex-direction: column;
}
.ai-metaobject-carousel__product-title-{{ ai_gen_id }} {
margin: 0 0 8px;
font-size: 16px;
font-weight: 600;
color: {{ block.settings.text_color }};
}
.ai-metaobject-carousel__product-title-{{ ai_gen_id }} a {
color: inherit;
text-decoration: none;
}
.ai-metaobject-carousel__product-title-{{ ai_gen_id }} a:hover {
opacity: 0.7;
}
.ai-metaobject-carousel__product-price-{{ ai_gen_id }} {
font-size: 14px;
color: {{ block.settings.text_color }};
margin-bottom: 10px;
}
.ai-metaobject-carousel__product-button-{{ ai_gen_id }} {
margin-top: auto;
padding: 10px 20px;
background-color: {{ block.settings.button_background_color }};
color: {{ block.settings.button_text_color }};
border: none;
border-radius: {{ block.settings.button_border_radius }}px;
cursor: pointer;
text-decoration: none;
display: inline-block;
text-align: center;
transition: background-color 0.3s ease;
}
.ai-metaobject-carousel__product-button-{{ ai_gen_id }}:hover {
background-color: {{ block.settings.button_hover_background_color }};
}
.ai-metaobject-carousel__nav-{{ ai_gen_id }} {
position: absolute;
top: 50%;
transform: translateY(-50%);
background-color: {{ block.settings.nav_button_background }};
color: {{ block.settings.nav_button_color }};
border: none;
width: 40px;
height: 40px;
border-radius: 50%;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
z-index: 2;
transition: opacity 0.3s ease;
}
.ai-metaobject-carousel__nav-{{ ai_gen_id }}:hover {
opacity: 0.8;
}
.ai-metaobject-carousel__nav-{{ ai_gen_id }}:disabled {
opacity: 0.3;
cursor: not-allowed;
}
.ai-metaobject-carousel__nav--prev-{{ ai_gen_id }} {
left: -20px;
}
.ai-metaobject-carousel__nav--next-{{ ai_gen_id }} {
right: -20px;
}
.ai-metaobject-carousel__empty-state-{{ ai_gen_id }} {
text-align: center;
padding: 60px 20px;
color: #999;
}
.ai-metaobject-carousel__empty-state-{{ ai_gen_id }} svg {
width: 80px;
height: 80px;
margin-bottom: 20px;
opacity: 0.3;
}
.ai-metaobject-carousel__empty-state-text-{{ ai_gen_id }} {
font-size: 16px;
font-style: italic;
}
@media screen and (max-width: 749px) {
.ai-metaobject-carousel__nav-{{ ai_gen_id }} {
width: 32px;
height: 32px;
}
.ai-metaobject-carousel__nav--prev-{{ ai_gen_id }} {
left: 0;
}
.ai-metaobject-carousel__nav--next-{{ ai_gen_id }} {
right: 0;
}
}
{% endstyle %}
<metaobject-carousel-{{ ai_gen_id }}
class="ai-metaobject-carousel-{{ ai_gen_id }}"
{{ block.shopify_attributes }}
>
<div class="ai-metaobject-carousel__container-{{ ai_gen_id }}">
{% if block.settings.heading != blank %}
<div class="ai-metaobject-carousel__header-{{ ai_gen_id }}">
<h2 class="ai-metaobject-carousel__heading-{{ ai_gen_id }}">{{ block.settings.heading }}</h2>
</div>
{% endif %}
{% if block.settings.product_list.count > 0 %}
<div class="ai-metaobject-carousel__wrapper-{{ ai_gen_id }}">
<button
class="ai-metaobject-carousel__nav-{{ ai_gen_id }} ai-metaobject-carousel__nav--prev-{{ ai_gen_id }}"
aria-label="Previous"
data-direction="prev"
>
<svg
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<polyline points="15 18 9 12 15 6"></polyline>
</svg>
</button>
<div class="ai-metaobject-carousel__track-{{ ai_gen_id }}">
{% for product in block.settings.product_list %}
<div class="ai-metaobject-carousel__slide-{{ ai_gen_id }}">
<div class="ai-metaobject-carousel__product-card-{{ ai_gen_id }}">
<a href="{{ product.url }}" class="ai-metaobject-carousel__product-image-{{ ai_gen_id }}">
{% if product.featured_image %}
<img
src="{{ product.featured_image | image_url: width: 600 }}"
alt="{{ product.featured_image.alt | escape }}"
loading="lazy"
width="600"
height="600"
>
{% else %}
<div class="ai-metaobject-carousel__product-image-placeholder-{{ ai_gen_id }}">
{{ 'product-1' | placeholder_svg_tag }}
</div>
{% endif %}
</a>
<div class="ai-metaobject-carousel__product-info-{{ ai_gen_id }}">
<h3 class="ai-metaobject-carousel__product-title-{{ ai_gen_id }}">
<a href="{{ product.url }}">{{ product.title }}</a>
</h3>
<div class="ai-metaobject-carousel__product-price-{{ ai_gen_id }}">
{{ product.price | money }}
</div>
<a
href="{{ product.url }}"
class="ai-metaobject-carousel__product-button-{{ ai_gen_id }}"
>
{{ block.settings.button_text }}
</a>
</div>
</div>
</div>
{% endfor %}
</div>
<button
class="ai-metaobject-carousel__nav-{{ ai_gen_id }} ai-metaobject-carousel__nav--next-{{ ai_gen_id }}"
aria-label="Next"
data-direction="next"
>
<svg
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<polyline points="9 18 15 12 9 6"></polyline>
</svg>
</button>
</div>
{% else %}
<div class="ai-metaobject-carousel__empty-state-{{ ai_gen_id }}">
{{ 'product-1' | placeholder_svg_tag }}
<div class="ai-metaobject-carousel__empty-state-text-{{ ai_gen_id }}">
Add products to display in the carousel
</div>
</div>
{% endif %}
</div>
</metaobject-carousel-{{ ai_gen_id }}>
<script>
(function() {
class MetaobjectCarousel{{ ai_gen_id }} extends HTMLElement {
constructor() {
super();
this.currentIndex = 0;
this.productsPerView = {{ block.settings.products_per_row }};
this.productsPerViewMobile = {{ block.settings.products_per_row_mobile }};
}
connectedCallback() {
this.track = this.querySelector('.ai-metaobject-carousel__track-{{ ai_gen_id }}');
this.slides = this.querySelectorAll('.ai-metaobject-carousel__slide-{{ ai_gen_id }}');
this.prevButton = this.querySelector('.ai-metaobject-carousel__nav--prev-{{ ai_gen_id }}');
this.nextButton = this.querySelector('.ai-metaobject-carousel__nav--next-{{ ai_gen_id }}');
if (!this.track || this.slides.length === 0) return;
this.setupEventListeners();
this.updateCarousel();
this.handleResize();
window.addEventListener('resize', () => this.handleResize());
}
setupEventListeners() {
this.prevButton.addEventListener('click', () => this.navigate('prev'));
this.nextButton.addEventListener('click', () => this.navigate('next'));
}
handleResize() {
this.currentProductsPerView = window.innerWidth <= 749 ? this.productsPerViewMobile : this.productsPerView;
this.updateCarousel();
}
navigate(direction) {
const maxIndex = Math.max(0, this.slides.length - this.currentProductsPerView);
if (direction === 'prev') {
this.currentIndex = Math.max(0, this.currentIndex - 1);
} else {
this.currentIndex = Math.min(maxIndex, this.currentIndex + 1);
}
this.updateCarousel();
}
updateCarousel() {
if (!this.track || this.slides.length === 0) return;
const slideWidth = this.slides[0].offsetWidth;
const gap = {{ block.settings.gap }};
const offset = this.currentIndex * (slideWidth + gap);
this.track.style.transform = `translateX(-${offset}px)`;
const maxIndex = Math.max(0, this.slides.length - this.currentProductsPerView);
this.prevButton.disabled = this.currentIndex === 0;
this.nextButton.disabled = this.currentIndex >= maxIndex;
}
}
customElements.define('metaobject-carousel-{{ ai_gen_id }}', MetaobjectCarousel{{ ai_gen_id }});
})();
</script>
{% schema %}
{
"name": "Product carousel",
"tag": null,
"settings": [
{
"type": "product_list",
"id": "product_list",
"label": "Products"
},
{
"type": "header",
"content": "Content"
},
{
"type": "text",
"id": "heading",
"label": "Heading",
"default": "Featured products"
},
{
"type": "select",
"id": "heading_alignment",
"label": "Heading alignment",
"options": [
{
"value": "left",
"label": "Left"
},
{
"value": "center",
"label": "Center"
},
{
"value": "right",
"label": "Right"
}
],
"default": "center"
},
{
"type": "text",
"id": "button_text",
"label": "Button text",
"default": "View product"
},
{
"type": "header",
"content": "Layout"
},
{
"type": "range",
"id": "products_per_row",
"min": 2,
"max": 5,
"step": 1,
"label": "Products per row (desktop)",
"default": 4
},
{
"type": "range",
"id": "products_per_row_mobile",
"min": 1,
"max": 3,
"step": 1,
"label": "Products per row (mobile)",
"default": 2
},
{
"type": "range",
"id": "gap",
"min": 0,
"max": 40,
"step": 4,
"unit": "px",
"label": "Gap between products",
"default": 20
},
{
"type": "range",
"id": "section_padding",
"min": 0,
"max": 100,
"step": 4,
"unit": "px",
"label": "Section padding",
"default": 40
},
{
"type": "header",
"content": "Colors"
},
{
"type": "color",
"id": "background_color",
"label": "Background",
"default": "#ffffff"
},
{
"type": "color",
"id": "heading_color",
"label": "Heading",
"default": "#000000"
},
{
"type": "color",
"id": "text_color",
"label": "Text",
"default": "#000000"
},
{
"type": "color",
"id": "card_background_color",
"label": "Card background",
"default": "#ffffff"
},
{
"type": "color",
"id": "card_border_color",
"label": "Card border",
"default": "#e6e6e6"
},
{
"type": "color",
"id": "button_background_color",
"label": "Button background",
"default": "#000000"
},
{
"type": "color",
"id": "button_text_color",
"label": "Button text",
"default": "#ffffff"
},
{
"type": "color",
"id": "button_hover_background_color",
"label": "Button hover background",
"default": "#333333"
},
{
"type": "color",
"id": "nav_button_background",
"label": "Navigation button background",
"default": "#000000"
},
{
"type": "color",
"id": "nav_button_color",
"label": "Navigation button icon",
"default": "#ffffff"
},
{
"type": "header",
"content": "Style"
},
{
"type": "range",
"id": "heading_size",
"min": 16,
"max": 48,
"step": 2,
"unit": "px",
"label": "Heading size",
"default": 32
},
{
"type": "range",
"id": "card_border_radius",
"min": 0,
"max": 20,
"step": 2,
"unit": "px",
"label": "Card border radius",
"default": 8
},
{
"type": "range",
"id": "card_border_width",
"min": 0,
"max": 4,
"step": 1,
"unit": "px",
"label": "Card border width",
"default": 1
},
{
"type": "range",
"id": "button_border_radius",
"min": 0,
"max": 40,
"step": 2,
"unit": "px",
"label": "Button border radius",
"default": 4
}
],
"presets": [
{
"name": "Product carousel"
}
]
}
{% endschema %}


