I have a Shopify store with products that either include both images and videos or just images. I want to make sure that if a product has a video, it is visible on the product page without requiring users to scroll through many images to find it.
I’m considering positioning the video right beneath the ‘Add to Cart’ button. Although I have figured out which template to edit, I’m running into issues with the Liquid code needed to check if a video exists and display it.
Here’s what I’ve been trying to do:
{% assign video_found = false %}
{% for media_item in product.media %}
{% if media_item.media_type == 'video' %}
<div class="video-container">
<video controls width="320" height="240">
<source src="{{ media_item.sources[0].url }}" type="video/mp4">
Your browser does not support the video tag.
</video>
</div>
{% assign video_found = true %}
{% break %}
{% endif %}
{% endfor %}
{% if video_found == false %}
<p>No video available for this product.</p>
{% endif %}
The current code is only returning the product title and not showing any video even when one is present. Could someone offer me tips on how to correctly identify video media and display it on the page? Any insights into the Liquid coding would be greatly appreciated.
The issue you’re encountering is likely due to how Shopify handles video media objects. Instead of accessing media_item.sources[0].url, you should use media_item.preview_image.alt to get the video URL or better yet, use the media_item object directly with Shopify’s built-in video rendering.
Try replacing your video display code with this approach:
The media_tag filter is specifically designed for rendering Shopify media objects and handles the video source URLs automatically. This should resolve your display issues. Also, make sure you’re testing with products that actually have video media uploaded through the Shopify admin, not just embedded videos from external sources.
Looking at your code, the main issue appears to be with the conditional logic placement. The problem might be that your video container is being created inside the loop but the browser isn’t rendering it properly. I encountered something similar when working on a client’s store last year.
What worked for me was restructuring the approach entirely. Instead of using a boolean flag, I found it more reliable to first filter the media collection for videos, then handle the display. Try this modification:
{% assign product_videos = product.media | where: 'media_type', 'video' %}
{% if product_videos.size > 0 %}
{% assign first_video = product_videos.first %}
<div class="video-container">
{{ first_video | video_tag: controls: true, width: 320, height: 240 }}
</div>
{% else %}
<p>No video available for this product.</p>
{% endif %}
This approach filters the media collection upfront and uses Shopify’s video_tag filter which handles the video sources more reliably than manually constructing the HTML. Make sure your theme supports the video_tag filter though, as some older themes might not have it.
hey @JackWolf69, had similar issue last month. your loop looks fine but the video_found variable might be the problem. try removing that logic and just use a simple check like {% unless product.media == blank %} first. also double check your product actually has video uploaded in admin panel - sometimes it shows as image instead of video if upload failed.