How to Add a Product Recommendation Quiz to Shopify Without an App
Shopify Product Recommendation Quiz Without an App: The Complete Build Guide
A product recommendation quiz does one job well: it turns a browsing shopper into a shopper with a specific product in their cart. On Shopify, the default answer is to install a quiz app, but that adds a monthly fee, another script on your storefront, and a data trail you don't control. You can build the same routing logic natively using theme sections, metafields, and Liquid. Here's how.
Why Build a Quiz Without an App (and When Not To)
The case for building it yourself:
- No recurring cost. Quiz apps typically bill monthly once you pass a free-tier response limit. Check current pricing on whichever app you're comparing against; the range is wide and changes often.
- No third-party script. Quiz apps load JavaScript on your storefront, which affects page speed and gives another vendor visibility into your traffic.
- Full control over logic and design. You decide how questions branch, what the results page looks like, and how products are ranked.
- Your data stays in Shopify. Responses can be stored as customer tags or order attributes rather than in a vendor's dashboard.
The case against:
- You need a theme you can edit. If you're on a locked or heavily customized theme you don't control, this gets painful.
- No built-in analytics dashboard. You'll wire up your own tracking (covered below).
- No A/B testing UI. You'll test manually.
- Complex branching is hard. Two or three questions with tag-based scoring is easy. A twenty-question adaptive quiz with weighted scoring across hundreds of SKUs is not — use an app for that.
If you sell under roughly 50 products and your recommendations map cleanly to tags, build it yourself.
How the No-App Quiz Works: Liquid, Metafields, and a Section
The mechanics are simple once you see the pieces:
- A theme section holds the quiz HTML, CSS, and JavaScript. You add it to a page through the theme editor, so no code deployment is needed after the initial build.
- Metafields store the mapping data — for example, a
custom.quiz_tagsmetafield on each product listing which quiz answers should surface it. - Liquid renders the product cards for each result, using the metafield values to filter.
- JavaScript handles the question flow client-side, then either reveals a pre-rendered result block or redirects to a filtered collection URL.
The cleanest approach for most stores: render every possible result set in Liquid, hide them with CSS, and let JavaScript show the matching one. That avoids AJAX calls and keeps the quiz fast.
Step 1: Map Your Questions to Products and Tags
Before writing any code, write the quiz on paper. Bad quizzes fail here, not in the Liquid.
Pick two or three questions maximum. Each question should split your catalog meaningfully. For a coffee store selling single-origin beans, a grinder, and a subscription:
- Question 1: How do you brew? (Pour-over / Espresso / French press / Drip)
- Question 2: How adventurous are you? (Classic and balanced / Bright and fruity / Whatever's freshest)
- Question 3: Whole bean or ground?
Now define tags that map to combinations. Use a consistent prefix so you don't collide with existing tags:
| Answer combination | Tag applied to product |
|---|---|
| Pour-over + Bright + Whole bean | quiz-pourover-bright-whole |
| Espresso + Classic + Ground | quiz-espresso-classic-ground |
| French press + Fruity + Whole bean | quiz-frenchpress-fruity-whole |
| Drip + Classic + Ground | quiz-drip-classic-ground |
Apply these tags to products in Products → [product] → Tags. A product can carry several quiz tags — that's fine and often desirable.
A few rules that keep this maintainable:
- Keep the tag prefix unique (
quiz-works). - Cap combinations at eight to twelve. More than that and you'll have tags with zero products.
- Every combination must have at least two products, or the result page looks broken.
- Tag products before you build the section, so you can test immediately.
If you'd rather not touch product tags, use a product metafield instead. Create a metafield definition under Settings → Custom data → Products with namespace custom and key quiz_tags, type List of single line text. Then enter the same values. Metafields are tidier but require editing each product's metafield panel; tags are faster to bulk-edit.
Step 2: Create the Quiz Section in Your Theme
In your Shopify admin, go to Online Store → Themes → Edit code. Under Sections, click Add a new section and name it quiz-recommender.
The section file needs three parts: schema, markup, and the result blocks.
Start with the schema so the section is configurable:
{% schema %}
{
"name": "Quiz Recommender",
"settings": [
{
"type": "text",
"id": "heading",
"label": "Quiz heading",
"default": "Find your perfect match"
},
{
"type": "text",
"id": "tag_prefix",
"label": "Quiz tag prefix",
"default": "quiz-"
}
],
"blocks": [
{
"type": "result",
"name": "Result set",
"settings": [
{
"type": "text",
"id": "result_key",
"label": "Result key (must match a quiz tag)"
},
{
"type": "text",
"id": "result_title",
"label": "Result headline"
}
]
}
],
"presets": [{ "name": "Quiz Recommender" }]
}
{% endschema %}
The blocks array is the important piece. Each block represents one outcome — one tag combination. You'll add a block per result set in the theme editor later.
Below the schema, render the quiz container and the hidden result sets:
<div class="quiz" data-quiz>
<h2>{{ section.settings.heading }}</h2>
<div class="quiz__step" data-step="1">
<p>How do you brew?</p>
<button data-answer="pourover">Pour-over</button>
<button data-answer="espresso">Espresso</button>
<button data-answer="frenchpress">French press</button>
<button data-answer="drip">Drip</button>
</div>
<div class="quiz__step" data-step="2" hidden>
<p>What flavor profile do you want?</p>
<button data-answer="bright">Bright and fruity</button>
<button data-answer="classic">Classic and balanced</button>
</div>
<div class="quiz__step" data-step="3" hidden>
<p>Whole bean or ground?</p>
<button data-answer="whole">Whole bean</button>
<button data-answer="ground">Ground</button>
</div>
<div class="quiz__results" hidden>
{% for block in section.blocks %}
{% assign tag = section.settings.tag_prefix | append: block.settings.result_key %}
<div class="quiz__result" data-result="{{ block.settings.result_key }}" hidden>
<h3>{{ block.settings.result_title }}</h3>
<div class="quiz__products">
{% for product in collections.all.products %}
{% if product.tags contains tag %}
<a href="{{ product.url }}">
<img src="{{ product.featured_image | image_url: width: 400 }}" alt="{{ product.title | escape }}" loading="lazy">
<span>{{ product.title }}</span>
<span>{{ product.price | money }}</span>
</a>
{% endif %}
{% endfor %}
</div>
</div>
{% endfor %}
</div>
</div>
Two things worth noting. collections.all.products caps at 50 products per page in some themes; if you have more, loop over a specific collection instead by adding a collection picker setting. And image_url is the modern filter — if your theme is older, it may use img_url instead. Check your theme's other sections to match the convention.
Step 3: Write the Liquid Logic That Routes Shoppers
The Liquid above renders every result set. JavaScript decides which one to show. Add this inside the section, after the markup:
<script>
(function () {
const quiz = document.querySelector('[data-quiz]');
if (!quiz) return;
const answers = {};
const steps = quiz.querySelectorAll('.quiz__step');
const results = quiz.querySelector('.quiz__results');
quiz.addEventListener('click', function (e) {
const btn = e.target.closest('button[data-answer]');
if (!btn) return;
const step = btn.closest('.quiz__step');
answers['q' + step.dataset.step] = btn.dataset.answer;
const next = step.nextElementSibling;
if (next && next.classList.contains('quiz__step')) {
next.hidden = false;
step.hidden = true;
} else {
step.hidden = true;
const key = [answers.q1, answers.q2, answers.q3].join('-');
results.hidden = false;
const match = results.querySelector('[data-result="' + key + '"]');
if (match) match.hidden = false;
else results.querySelector('.quiz__result').hidden = false; // fallback
}
});
})();
</script>
The key is built by joining answers with hyphens, which must match your tag suffix. If a shopper's combination has no matching result block, the fallback shows the first result set rather than an empty page — never leave a dead end.
If you'd rather redirect to a filtered collection instead of showing inline results, replace the result reveal with:
window.location.href = '/collections/all/' + key;
That requires collection filters set up for those tags. Inline results are simpler and keep the shopper on the page.
Step 4: Add the Quiz to a Page With the Theme Editor
Create a page first: Online Store → Pages → Add page, title it "Find Your Coffee," and set the handle to find-your-coffee. Leave the body empty.
Then go to Online Store → Themes → Customize, navigate to the page you just created using the page selector at the top, and click Add section → Quiz Recommender.
Now add one Result set block per tag combination. The result_key must be the tag suffix without the prefix — for quiz-pourover-bright-whole, enter pourover-bright-whole. Set a headline for each, like "Bright pour-over beans for you."
Save. Visit the page on your storefront and click through every path. Check that:
- Each combination shows the right products.
- No result set is empty.
- The quiz works on mobile — tap targets should be at least 44px tall.
Testing, Tracking, and Improving Your Quiz Results
Before you promote the quiz, verify the mapping. Open your tag list in Products → Tags and confirm every quiz- tag has at least two products assigned. An empty result set is the most common failure and the most damaging.
For tracking, fire a Shopify analytics event when a result is shown. Add this to the reveal logic:
window.ShopifyAnalytics?.lib?.track('quiz_completed', { result: key });
Then compare conversion rate for sessions that hit the quiz page against your site average in Analytics → Reports. If you use Google Analytics 4, push the same event to the data layer and mark it as a conversion.
Improvements worth testing, in order of impact:
- Rewrite the questions. If one answer option is picked by 80% of shoppers, it isn't segmenting anyone. Replace it.
- Reorder results. Put your highest-margin product in the first position of each result set.
- Add a "why this" line. A sentence explaining the match ("You chose bright and fruity, so we picked beans from Ethiopia") lifts click-through noticeably.
- Cut a question. Three questions convert better than five. Two often beats three.
Review the quiz monthly. Coffee catalogs rotate seasonally, so tags drift out of date fast.
Conclusion
A no-app product recommendation quiz on Shopify is a theme section, a set of tags or metafields, and about forty lines of JavaScript. It costs nothing per month, keeps shopper data in your store, and gives you total control over the recommendation logic. Build it once for a focused catalog, keep the tag mapping current, and it will outperform a generic quiz widget.
FAQ
Do I need to know how to code? You need to copy and paste Liquid and JavaScript accurately and edit a few values. If you can follow a tutorial and use the theme code editor without panicking, you can do this. If your theme is custom-built or you're not comfortable editing it, hire a Shopify developer for a one-time build.
Will this work on any Shopify theme? It works on any Online Store 2.0 theme that supports sections, which includes Dawn, Refresh, Craft, and most paid themes from recent years. Older vintage themes without section support need a different approach. Check whether your theme's Customize screen lets you add sections to pages.
What if a shopper's answers don't match any tag combination? The fallback in the code shows the first result set instead of an empty page. Better practice is to design your questions so every combination maps to a tag — with two questions of four and three options, that's twelve combinations, which is manageable to tag manually.