Video Testimonials voor Shopify: Een Krachtige Snippet Oplossing

Video Testimonials voor Shopify: Een Krachtige Snippet Oplossing

Deze handleiding laat je zien hoe je een professionele video testimonials carousel toevoegt aan elk Shopify block - of dat nu in je product template is, een custom landing page, of zelfs in je cart drawer.

Jul 17, 2025

Door Diek Thunnissen

Waarom deze aanpak anders is

In mijn jaren als Shopify developer heb ik talloze winkeleigenaren zien worstelen met video testimonials. Ze proberen YouTube embeds (traag en niet mobiel-vriendelijk), installeren dure apps (€30+ per maand), of huren een developer in voor custom werk. Maar wat als ik je vertel dat er een elegantere oplossing is?

Deze handleiding laat je zien hoe je een professionele video testimonials carousel toevoegt aan elk Shopify block - of dat nu in je product template is, een custom landing page, of zelfs in je cart drawer. Het geheim? Een slim opgezette snippet die je overal kunt hergebruiken.

De kracht van een snippet-based oplossing

Voordat we in de code duiken, laat me uitleggen waarom deze aanpak zo krachtig is. In plaats van een standalone section te maken (wat de meeste tutorials doen), bouwen we een herbruikbare snippet. Dit betekent dat je video testimonials kunt toevoegen aan:

  • Product templates (onder de prijs, bij de beschrijving, waar je maar wilt)
  • Custom sections die je al hebt
  • Theme blocks zoals featured products of collections
  • Zelfs in je header of footer als je dat zou willen

De flexibiliteit is enorm, en het beste deel? Je hoeft de code maar één keer te installeren.

Stap 1: De snippet installeren

We beginnen met het hart van onze oplossing. Log in op je Shopify admin en navigeer naar Online Store > Themes. Bij je actieve thema klik je op Actions > Edit code.

In de sidebar zie je verschillende mappen. Klik op Snippets en dan op Add a new snippet. Noem het snippet video-testimonials-advanced (zonder .liquid).

Nu komt de magie. Plak de volgende code in je nieuwe snippet:

liquid

{% comment %}  Video Testimonials met Swiper.js
 Gebruik: {% render 'video-testimonials-advanced', block: block %}
 Ontwikkeld door Diek Thunnissen - https://diekthunnissen.nl
{% endcomment %}

{% liquid
 assign snippet_title = block.settings.title | default: "Loved by 100,000+ happy customers."
 assign title_size = block.settings.title_size | default: 'h6'
 assign title_alignment = block.settings.title_alignment | default: 'center'
 assign title_color = block.settings.title_color | default: '#222222'
 assign show_title = block.settings.show_title | default: true
 assign show_controls = block.settings.show_controls | default: true
 assign autoplay_first = block.settings.autoplay_first | default: true
 assign videos_per_view = block.settings.videos_per_view | default: 3
 assign aspect_ratio = block.settings.aspect_ratio | default: 0.5625

 # Collect videos that are set
 assign video_count = 0
 for i in (1..8)
   assign video_key = 'video_' | append: i
   if block.settings[video_key] != blank
     assign video_count = video_count | plus: 1
   endif
 endfor
%}

{% if video_count > 0 %}
<!-- Swiper CSS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.css" />

<div class="videoblock">
 {% if snippet_title != blank and show_title %}
   <videotitle class="{{ title_size }}" style="margin-bottom: 20px; text-align: {{ title_alignment }}; display: block; color: {{ title_color }};">
     {{ snippet_title }}
   </videotitle>
 {% endif %}

 <div style="margin-top: 10px; margin-bottom: 10px;" class="video-slider">
   <div class="swiper Videoslider">
     <div class="swiper-wrapper">

       {% for i in (1..8) %}
         {% liquid
           assign video_key = 'video_' | append: i
           assign thumbnail_key = 'video_' | append: i | append: '_thumbnail'
           assign video = block.settings[video_key]
           assign thumbnail = block.settings[thumbnail_key]
         %}

         {% if video != blank %}
           <div class="swiper-slide">
             <div class="video-slide" data-video-id="{{ forloop.index }}">
               <div class="thumbnailimg">
                 <i class="fa-solid fa-circle-play"></i>
                 {% if thumbnail != blank %}
                   {{ thumbnail | image_url: width: 500 | image_tag:
                     class: 'video-thumbnail',
                     width: 135,
                     height: 240,
                     loading: 'lazy',
                     alt: 'Video Preview'
                   }}
                 {% elsif video.preview_image != blank %}
                   {{ video.preview_image | image_url: width: 500 | image_tag:
                     class: 'video-thumbnail',
                     width: 135,
                     height: 240,
                     loading: 'lazy',
                     alt: 'Video Preview'
                   }}
                 {% else %}
                   <div class="video-thumbnail video-thumbnail--placeholder">
                     <span>Video {{ i }}</span>
                   </div>
                 {% endif %}
               </div>

               <div class="video-container" style="display:none;">
                 {{ video | video_tag:
                   controls: true,
                   muted: true,
                   playsinline: true,
                   width: 135,
                   height: 240,
                   style: 'border-radius: 8px; width: 100%; height: 100%; object-fit: cover;'
                 }}
               </div>
             </div>
           </div>
         {% endif %}
       {% endfor %}

     </div>

     
<!-- Swiper scrollbar -->
     <div class="swiper-scrollbar swiper-scrollbar_Videoslider"></div>
   </div>
 </div>
</div>

<style>
.videoblock {
 padding: 40px 0;
 width: 100%;
 max-width: 100%;
 overflow: hidden;
}

.h3 {
 font-size: 36px;
 font-weight: 600;
 margin: 0;
}

.h4 {
 font-size: 32px;
 font-weight: 600;
 margin: 0;
}

.h5 {
 font-size: 30px;
 font-weight: 500;
 margin: 0;
}

.h6 {
 font-size: 28px;
 font-weight: 500;
 margin: 0;
}

.body-lg {
 font-size: 20px;
 font-weight: 400;
 margin: 0;
}

.body {
 font-size: 16px;
 font-weight: 400;
 margin: 0;
}

.video-slider {
 position: relative;
 width: 100%;
}

.swiper {
 width: 100%;
 height: auto;
}

.swiper-slide {
 width: auto !important;
 margin-right: 9px !important;
}

.video-slide {
 position: relative;
 cursor: pointer;
 width: 135px;
 height: 240px;
 display: inline-block;
}

.thumbnailimg {
 position: relative;
 width: 100%;
 height: 100%;
 border-radius: 8px;
 overflow: hidden;
}

.video-thumbnail {
 width: 100%;
 height: 100%;
 object-fit: cover;
 display: block;
}

.video-thumbnail--placeholder {
 width: 100%;
 height: 100%;
 background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
 display: flex;
 align-items: center;
 justify-content: center;
 color: white;
 font-size: 14px;
 font-weight: 500;
}

.fa-circle-play {
 position: absolute;
 top: 50%;
 left: 50%;
 transform: translate(-50%, -50%);
 font-size: 48px;
 color: rgba(255, 255, 255, 0.9);
 z-index: 2;
 pointer-events: none;
 filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.3));
}

.video-container {
 width: 100%;
 height: 100%;
 position: absolute;
 top: 0;
 left: 0;
}

.video-container video {
 width: 100%;
 height: 100%;
 object-fit: cover;
}

/* Swiper scrollbar styling */
.swiper-scrollbar {
 position: relative !important;
 height: 4px !important;
 background: rgba(0, 0, 0, 0.08) !important;
 border-radius: 2px !important;
 margin-top: 20px !important;
}

.swiper-scrollbar-drag {
 background: linear-gradient(90deg, #4a4a4a, #2c2c2c) !important;
 border-radius: 2px !important;
 height: 100% !important;
 opacity: 0.8;
 transition: opacity 0.3s ease;
}

.swiper-scrollbar-drag:hover {
 opacity: 1;
}

/* Mobile responsiveness */
@media (max-width: 768px) {
 .videoblock {
   padding: 30px 0;
 }

 .h3 { font-size: 28px; }
 .h4 { font-size: 24px; }
 .h5 { font-size: 22px; }
 .h6 { font-size: 20px; }
 .body-lg { font-size: 18px; }

 .video-slider {
   padding: 0 20px;
 }

 .swiper {
   margin: 0 -20px;
   padding: 0 20px;
 }
}

@media (max-width: 480px) {
 .h3 { font-size: 24px; }
 .h4 { font-size: 22px; }
 .h5 { font-size: 20px; }
 .h6 { font-size: 18px; }

 .video-slide {
   width: 120px;
   height: 213px;
 }

 .fa-circle-play {
   font-size: 40px;
 }
}

/* Desktop - show more videos */
@media (min-width: 1024px) {
 .video-slide {
   width: 160px;
   height: 284px;
 }
}

@media (min-width: 1440px) {
 .video-slide {
   width: 180px;
   height: 320px;
 }
}
</style>

<!-- Font Awesome for play icon -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">

<!-- Swiper JS -->
<script src="https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.js"></script>

<script>
// Video play functionality
document.addEventListener('click', function(e) {
 
// Check if clicking on a video slide
 const videoSlide = e.target.closest('.video-slide');
 if (!videoSlide) return;

 
// Prevent multiple clicks
 if (videoSlide.classList.contains('playing')) return;

 const thumbnail = videoSlide.querySelector('.thumbnailimg');
 const videoContainer = videoSlide.querySelector('.video-container');
 const video = videoContainer?.querySelector('video');

 if (!video) {
   console.error('Video element not found');
   return;
 }

 
// Hide thumbnail and show video
 thumbnail.style.display = 'none';
 videoContainer.style.display = 'block';
 videoSlide.classList.add('playing');

 
// Reset video and play
 video.currentTime = 0;
 video.muted = true;
// Ensure muted for autoplay

 
// Try to play
 const playPromise = video.play();

 if (playPromise !== undefined) {
   playPromise.then(() => {
     console.log('Video is playing');
   }).catch(error => {
     console.error('Error playing video:', error);
     
// If autoplay fails, show controls
     video.controls = true;
   });
 }

 
// Stop all other videos
 document.querySelectorAll('.video-slide.playing').forEach(slide => {
   if (slide !== videoSlide) {
     const otherVideo = slide.querySelector('video');
     const otherThumbnail = slide.querySelector('.thumbnailimg');
     const otherContainer = slide.querySelector('.video-container');

     if (otherVideo && !otherVideo.paused) {
       otherVideo.pause();
       otherVideo.currentTime = 0;
     }

     if (otherThumbnail) otherThumbnail.style.display = 'block';
     if (otherContainer) otherContainer.style.display = 'none';
     slide.classList.remove('playing');
   }
 });

 
// Handle video ended
 video.addEventListener('ended', function handleEnded() {
   thumbnail.style.display = 'block';
   videoContainer.style.display = 'none';
   videoSlide.classList.remove('playing');
   video.removeEventListener('ended', handleEnded);
 });
});

// Initialize Swiper when DOM is ready
function initVideoSwiper() {
 const swiper = new Swiper('.Videoslider', {
   slidesPerView: 'auto',
   spaceBetween: 9,
   freeMode: true,
   scrollbar: {
     el: '.swiper-scrollbar_Videoslider',
     draggable: true,
     dragSize: 'auto'
   },
   breakpoints: {
     320: {
       slidesPerView: 'auto',
       spaceBetween: 9
     },
     768: {
       slidesPerView: 'auto',
       spaceBetween: 12
     },
     1024: {
       slidesPerView: 'auto',
       spaceBetween: 15
     }
   }
 });
}

// Initialize when DOM is ready
if (document.readyState === 'loading') {
 document.addEventListener('DOMContentLoaded', initVideoSwiper);
} else {
 initVideoSwiper();
}

// Reinitialize when Shopify theme editor reloads sections
document.addEventListener('shopify:section:load', function() {
 setTimeout(initVideoSwiper, 100);
});
</script>

{% endif %}

Deze code is het complete video testimonials systeem. Laat me de belangrijkste onderdelen uitleggen:

Het Liquid gedeelte bovenaan verzamelt alle settings van het block waar de snippet in wordt gebruikt. Het telt hoeveel video's er zijn geconfigureerd en stelt defaults in voor alle opties.

Het HTML gedeelte bouwt de carousel structuur. Voor elke geconfigureerde video maakt het een slide met een thumbnail en een verborgen video container. Als er geen custom thumbnail is opgegeven, gebruikt het automatisch de video preview van Shopify.

De CSS zorgt voor alle styling en responsive gedrag. Let vooral op de media queries onderaan - die zorgen ervoor dat de video's er op elk schermformaat goed uitzien.

Het JavaScript handelt alle interacties af. Wanneer iemand op een thumbnail klikt, verbergt het de thumbnail, toont de video, en speelt deze af. Het zorgt er ook voor dat slechts één video tegelijk speelt.

Stap 2: Het block toevoegen aan een bestaande template

Nu komt het interessante deel - hoe gebruik je deze snippet? Ik zal je twee voorbeelden geven: één voor een product template en één voor het maken van een custom section.

Voorbeeld 1: Toevoegen aan je product template

Open het bestand waar je de video testimonials wilt toevoegen, bijvoorbeeld main-product.liquid. Zoek naar de regel {%- case block.type -%} (meestal ergens rond regel 200-400).

Voeg deze code toe binnen de case statement:

liquid

{%- when 'video_testimonials' -%}
 <div class="product-video-testimonials" {{ block.shopify_attributes }}>
   {% render 'video-testimonials-advanced', block: block %}
 </div>

Scroll nu naar beneden in hetzelfde bestand tot je het {% schema %} gedeelte vindt. Binnen de "blocks" array, voeg je dit block type toe:

json

{
 "type": "video_testimonials",
 "name": "📹 Video Testimonials",
 "limit": 1,
 "settings": [
   {
     "type": "header",
     "content": "Titel instellingen"
   },
   {
     "type": "text",
     "id": "title",
     "label": "Titel",
     "default": "Wat klanten zeggen"
   },
   {
     "type": "checkbox",
     "id": "show_title",
     "label": "Toon titel",
     "default": true
   },
   {
     "type": "select",
     "id": "title_size",
     "label": "Titel grootte",
     "options": [
       {
         "value": "h3",
         "label": "Extra groot (H3)"
       },
       {
         "value": "h4",
         "label": "Groot (H4)"
       },
       {
         "value": "h5",
         "label": "Medium groot (H5)"
       },
       {
         "value": "h6",
         "label": "Medium (H6)"
       },
       {
         "value": "body-lg",
         "label": "Grote tekst"
       },
       {
         "value": "body",
         "label": "Normale tekst"
       }
     ],
     "default": "h6"
   },
   {
     "type": "select",
     "id": "title_alignment",
     "label": "Titel uitlijning",
     "options": [
       {
         "value": "left",
         "label": "Links"
       },
       {
         "value": "center",
         "label": "Gecentreerd"
       },
       {
         "value": "right",
         "label": "Rechts"
       }
     ],
     "default": "center"
   },
   {
     "type": "color",
     "id": "title_color",
     "label": "Titel kleur",
     "default": "#222222"
   },
   {
     "type": "header",
     "content": "Video instellingen"
   },
   {
     "type": "checkbox",
     "id": "show_controls",
     "label": "Toon video controls",
     "default": true
   },
   {
     "type": "checkbox",
     "id": "autoplay_first",
     "label": "Autoplay eerste video",
     "default": true
   },
   {
     "type": "select",
     "id": "aspect_ratio",
     "label": "Video aspect ratio",
     "options": [
       {
         "value": "0.5625",
         "label": "16:9 (Landscape)"
       },
       {
         "value": "0.75",
         "label": "4:3 (Standard)"
       },
       {
         "value": "1.7778",
         "label": "9:16 (Portrait)"
       }
     ],
     "default": "1.7778"
   },
   {
     "type": "header",
     "content": "Video 1"
   },
   {
     "type": "video",
     "id": "video_1",
     "label": "Video 1"
   },
   {
     "type": "image_picker",
     "id": "video_1_thumbnail",
     "label": "Custom thumbnail (optioneel)"
   },
   {
     "type": "header",
     "content": "Video 2"
   },
   {
     "type": "video",
     "id": "video_2",
     "label": "Video 2"
   },
   {
     "type": "image_picker",
     "id": "video_2_thumbnail",
     "label": "Custom thumbnail (optioneel)"
   },
   {
     "type": "header",
     "content": "Video 3"
   },
   {
     "type": "video",
     "id": "video_3",
     "label": "Video 3"
   },
   {
     "type": "image_picker",
     "id": "video_3_thumbnail",
     "label": "Custom thumbnail (optioneel)"
   },
   {
     "type": "header",
     "content": "Video 4"
   },
   {
     "type": "video",
     "id": "video_4",
     "label": "Video 4"
   },
   {
     "type": "image_picker",
     "id": "video_4_thumbnail",
     "label": "Custom thumbnail (optioneel)"
   },
   {
     "type": "header",
     "content": "Video 5"
   },
   {
     "type": "video",
     "id": "video_5",
     "label": "Video 5"
   },
   {
     "type": "image_picker",
     "id": "video_5_thumbnail",
     "label": "Custom thumbnail (optioneel)"
   },
   {
     "type": "header",
     "content": "Video 6"
   },
   {
     "type": "video",
     "id": "video_6",
     "label": "Video 6"
   },
   {
     "type": "image_picker",
     "id": "video_6_thumbnail",
     "label": "Custom thumbnail (optioneel)"
   },
   {
     "type": "header",
     "content": "Video 7"
   },
   {
     "type": "video",
     "id": "video_7",
     "label": "Video 7"
   },
   {
     "type": "image_picker",
     "id": "video_7_thumbnail",
     "label": "Custom thumbnail (optioneel)"
   },
   {
     "type": "header",
     "content": "Video 8"
   },
   {
     "type": "video",
     "id": "video_8",
     "label": "Video 8"
   },
   {
     "type": "image_picker",
     "id": "video_8_thumbnail",
     "label": "Custom thumbnail (optioneel)"
   }
 ]
}

Voorbeeld 2: Een standalone section maken

Als je liever een aparte section wilt die je overal kunt gebruiken, maak dan een nieuw bestand in de Sections map genaamd video-testimonials.liquid:

liquid

<section class="vt-section page-width">
 {% render 'video-testimonials-advanced', block: section %}
</section>

{% schema %}
{
 "name": "📹 Video Testimonials",
 "settings": [
   // Hier dezelfde settings array als hierboven
 ],
 "presets": [
   {
     "name": "📹 Video Testimonials"
   }
 ]
}
{% endschema %}

Hoe het werkt in de praktijk

Nu je de code hebt geïnstalleerd, laten we kijken hoe je het gebruikt. Ga naar de Theme Customizer en navigeer naar een productpagina (als je het aan je product template hebt toegevoegd). Je zult nu een nieuw block type zien: 📹 Video Testimonials.

Voeg het block toe en je krijgt direct toegang tot alle configuratie-opties. Upload je video's via de Shopify Files uploader - houd ze onder de 10MB voor optimale performance. Het systeem accepteert MP4 video's, wat de standaard is voor web video.

Voor elke video kun je optioneel een custom thumbnail toevoegen. Dit is de afbeelding die bezoekers zien voordat ze op play klikken. Een goede thumbnail kan het verschil maken tussen wel of niet klikken. Als je geen thumbnail toevoegt, gebruikt het systeem automatisch de eerste frame van de video.

Geavanceerde aanpassingen

De kracht van deze snippet-aanpak is dat je hem overal kunt gebruiken. Hier zijn enkele creatieve toepassingen:

In je cart drawer

Voeg overtuigende testimonials toe net voordat mensen afrekenen. Dit kan die laatste twijfel wegnemen.

Op collection pages

Toon product-specifieke testimonials bovenaan je collectiepagina's om direct vertrouwen op te bouwen.

In je footer

Een kleine testimonials carousel in je footer houdt social proof zichtbaar op elke pagina.

Als pop-up

Combineer de snippet met een modal/pop-up systeem om testimonials te tonen wanneer mensen de site willen verlaten.

Performance optimalisatie

Deze oplossing is ontworpen met performance in gedachten. De video's laden pas wanneer iemand erop klikt, wat betekent dat de initiële paginalaadtijd minimaal wordt beïnvloed. De thumbnails worden lazy loaded, dus alleen zichtbare thumbnails worden geladen.

Voor nog betere performance, overweeg deze tips:

Comprimeer je video's met tools zoals HandBrake. Doel op ongeveer 1-2MB per 30 seconden video. De kwaliteit hoeft niet 4K te zijn - 720p is meer dan voldoende voor testimonials.

Optimaliseer je thumbnails naar exact 500x889px voor portrait video's. Dit voorkomt dat Shopify ze moet resizen, wat server resources bespaart.

Als je veel video's hebt, overweeg dan om ze te verdelen over meerdere pagina's in plaats van alles op één pagina te laden.

Troubleshooting

Soms kunnen er kleine problemen optreden. Hier zijn de meest voorkomende en hun oplossingen:

Als video's niet afspelen op mobiel, komt dit meestal door autoplay restricties. Onze code speelt video's gemuted af om dit te omzeilen, maar sommige oudere browsers kunnen nog steeds problemen geven. De fallback is dat gebruikers dan handmatig op play moeten drukken.

Als de carousel niet smooth werkt, check of er geen conflicterende JavaScript libraries zijn. Sommige thema's laden hun eigen versie van Swiper.js. Je kunt dit oplossen door onze Swiper instantie een unieke namespace te geven.

Als thumbnails niet worden getoond, controleer het formaat van je afbeeldingen. Gebruik JPG of PNG formaat, geen WebP of AVIF (nog niet breed ondersteund).

De business impact

Laten we even stilstaan bij waarom dit zo waardevol is voor je winkel. Video testimonials hebben een bewezen impact op conversie. Ze bouwen vertrouwen op, tonen je product in actie, en creëren een emotionele connectie met potentiële kopers.

Maar de meeste Shopify winkels gebruiken ze niet, of gebruiken ze slecht. YouTube embeds zijn traag en tonen het YouTube logo. Apps kosten geld en geven je weinig controle. Deze oplossing geeft je het beste van beide werelden: professionele functionaliteit zonder de kosten.

Conclusie

Met deze snippet heb je nu een krachtige, flexibele oplossing voor video testimonials die je overal in je Shopify winkel kunt gebruiken. Het is geen quick fix of tijdelijke oplossing - het is een professionele implementatie die meegroeit met je business.

Het mooiste? Je hebt volledige controle. Geen maandelijkse kosten, geen beperkingen, geen vendor lock-in. Gewoon pure functionaliteit die je klanten waarderen en die je conversie verhoogt.

Begin met een paar goede video's van je beste klanten. Vraag ze om kort (15-30 seconden) en specifiek te zijn over wat ze fijn vinden aan je product. Authenticiteit wint het altijd van productiewaarde.

Over de auteur

Diek Thunnissen
Shopify Developer & E-commerce Specialist

Ik help Shopify winkels groeien met slimme, technische oplossingen die écht werken. Van conversion optimization tot custom functionaliteit - altijd met focus op resultaat en gebruikerservaring.

🌐 diekthunnissen.nl
📧 info@diekthunnissen.nl

P.S. Heb je deze oplossing geïmplementeerd? Ik ben benieuwd naar je resultaten! Deel gerust je ervaringen of stel vragen - ik help graag verder.

Over Diek Thunnissen

Al sinds mijn vijftiende bouw ik websites. Nu, 10+ jaar en 50+ projecten verder, combineer ik design, Shopify‑development en data‑gedreven marketing tot één 360° e‑commerce‑aanpak.

User Icon - Personalfolio X Webflow Template
Meer over mij

Volg mij op social media

Check me op socials voor updates, tips en een kijkje achter de schermen.