Loading
Copy-paste a theme-editor section for trust & social proof - A rotating customer quote with stars and name - real social proof under the title or buy button.
“Exactly as described, quality is way better than I expected for the price.”
Priya · Mumbai
{%- comment -%} IMPORTANT: use real reviews. Fabricated testimonials breach consumer protection rules in most markets and kill trust when discovered.{%- endcomment -%}{%- if section.blocks.size > 0 -%} <div class="gpl-quotes" data-gpl-quotes data-gpl-autoplay="5000" style="--gpl-accent: {{ section.settings.accent }};"> {%- for block in section.blocks -%} <figure class="gpl-quotes__item {% if forloop.first %}is-active{% endif %}" {{ block.shopify_attributes }} {% unless forloop.first %}hidden{% endunless %}> <div class="gpl-quotes__stars" aria-label="{{ block.settings.stars }} out of 5 stars"> {%- for i in (1..5) -%} <svg viewBox="0 0 20 20" {% if i > block.settings.stars %}class="is-dim"{% endif %} aria-hidden="true"><path d="M10 1.5l2.6 5.3 5.9.9-4.2 4.1 1 5.8-5.3-2.8-5.3 2.8 1-5.8L1.5 7.7l5.9-.9z"/></svg> {%- endfor -%} </div> <blockquote class="gpl-quotes__text">“{{ block.settings.quote | escape }}”</blockquote> <figcaption class="gpl-quotes__name">{{ block.settings.name | escape }}{% if block.settings.role != blank %} · {{ block.settings.role | escape }}{% endif %}</figcaption> </figure> {%- endfor -%} {%- if section.blocks.size > 1 -%} <div class="gpl-quotes__dots" role="tablist" aria-label="Testimonials"> {%- for block in section.blocks -%} <button type="button" class="gpl-quotes__dot {% if forloop.first %}is-active{% endif %}" data-gpl-quote-dot="{{ forloop.index0 }}" aria-label="Show testimonial {{ forloop.index }}"></button> {%- endfor -%} </div> {%- endif -%} </div>{%- endif -%} {% schema %}{ "name": "Testimonial strip", "settings": [ { "type": "color", "id": "accent", "label": "Star colour", "default": "#f59e0b" } ], "blocks": [ { "type": "quote", "name": "Testimonial", "settings": [ { "type": "range", "id": "stars", "label": "Stars", "min": 1, "max": 5, "step": 1, "default": 5 }, { "type": "textarea", "id": "quote", "label": "Quote", "default": "Great quality - exactly as described." }, { "type": "text", "id": "name", "label": "Customer name", "default": "Verified buyer" }, { "type": "text", "id": "role", "label": "Context (optional)", "default": "Mumbai" } ] } ], "max_blocks": 8, "presets": [{ "name": "Testimonial strip", "blocks": [{ "type": "quote" }, { "type": "quote" }] }]}{% endschema %} {% stylesheet %}.gpl-quotes { text-align: center; padding: 1rem 0; }.gpl-quotes__item[hidden] { display: none; }.gpl-quotes__item { margin: 0; }.gpl-quotes__stars { display: flex; justify-content: center; gap: 2px; margin-bottom: 0.6rem; }.gpl-quotes__stars svg { width: 1rem; height: 1rem; fill: var(--gpl-accent); }.gpl-quotes__stars svg.is-dim { fill: rgb(var(--color-foreground, 148 163 184) / 0.25); }.gpl-quotes__text { margin: 0; font-size: 1rem; font-weight: 500; line-height: 1.55; }.gpl-quotes__name { margin-top: 0.6rem; font-size: 0.78rem; opacity: 0.6; }.gpl-quotes__dots { display: flex; justify-content: center; gap: 0.4rem; margin-top: 1rem; }.gpl-quotes__dot { width: 0.5rem; height: 0.5rem; border: 0; border-radius: 999px; padding: 0; background: rgb(var(--color-foreground, 148 163 184) / 0.3); cursor: pointer; transition: background 0.2s ease, transform 0.2s ease;}.gpl-quotes__dot.is-active { background: var(--gpl-accent); transform: scale(1.2); }{% endstylesheet %} {% javascript %}document.querySelectorAll('[data-gpl-quotes]').forEach((root) => { const items = Array.from(root.querySelectorAll('.gpl-quotes__item')); const dots = Array.from(root.querySelectorAll('[data-gpl-quote-dot]')); if (items.length < 2) return; let i = 0; const show = (n) => { i = (n + items.length) % items.length; items.forEach((el, j) => (el.hidden = j !== i)); dots.forEach((d, j) => d.classList.toggle('is-active', j === i)); }; dots.forEach((d, j) => d.addEventListener('click', () => show(j))); const delay = parseInt(root.getAttribute('data-gpl-autoplay'), 10); if (delay > 0 && !window.matchMedia('(prefers-reduced-motion: reduce)').matches) { let t = setInterval(() => show(i + 1), delay); root.addEventListener('mouseenter', () => clearInterval(t)); root.addEventListener('mouseleave', () => (t = setInterval(() => show(i + 1), delay))); }});{% endjavascript %}