The theme settings cover colors, fonts and buttons. When you want the quiz to look completely like your own design, give the theme custom code: one stylesheet for the whole quiz and your own HTML templates for the start page, the questions, the loading screen, the pre-result page and the product check page. bluebarry keeps doing everything the quiz does, so your code only decides where things go and how they look.
Open Custom code
- Go to Quizzes, click Edit on your quiz and open the Design tab in the left panel.
- Click Edit on the theme this quiz uses. Custom code only opens for that theme, because the editor previews this quiz.
- Scroll to the bottom of the theme settings and click Custom code.
The editor has six tabs: CSS, Start page, Question, Loading, Pre-result and Product check. Next to them is a live preview of this quiz with a desktop and a mobile button. The line at the top names the quizzes that use this theme. If it is your store's default theme, quizzes without a theme of their own use it too.
- An empty tab keeps the built-in screen. Click Start from an example to get working code to edit.
- Your code saves on its own shortly after you stop typing. If it has an error, the editor shows what to fix under the field and does not save it, so a live quiz never gets a broken design.
- On the Product check tab, pick a product next to Run the preview on a product page to preview the page as shoppers see it on that product.
CSS
One stylesheet styles every screen of the quiz, including the result page, the product check page and the error page. It only applies inside the quiz, and it wins over the theme's colors without !important. Motion and position properties, such as transform, opacity, transition and position, keep their normal weight so the quiz animations keep working. A custom result page (beta) has its own markup and CSS, so the result page classes below do not apply to it.
.bb-q-answer {
border: 1px solid var(--bb-color-title);
border-radius: var(--bb-radius, 8px);
}
.bb-q-answer[data-selected] {
background: var(--bb-color-button);
color: var(--bb-color-button-text);
}
@media (max-width: 480px) {
.bb-q-answers { grid-template-columns: 1fr; }
}- A width
@mediaquery follows the width of the quiz, not the browser window, so it also works in a pop-up, a side panel and the mobile preview. - Classes that start with
bb-q-are a stable, public contract, exceptbb-q-i-classes: those are internal and can change at any time. Give classes you add yourself a name without thebb-prefix. - The theme's settings are available as variables:
--bb-color-button,--bb-color-button-text,--bb-color-background,--bb-color-title,--bb-color-accent,--bb-color-answer,--bb-color-answer-text,--bb-font-body,--bb-font-titleand--bb-radius. A setting the theme leaves empty has no variable, so add a fallback. - Style states with
[data-selected]on a selected answer,aria-pressedon multi-select answers,:disabledon buttons that cannot be used yet,aria-invalidon an input with an error anddata-stateon an add to cart button. - Answers darken on hover by default. For a hover style of your own, turn that off with
.bb-q-answer:hover { filter: none; }.
| Part | Classes |
|---|---|
| Header | bb-q-header, bb-q-header-bar, bb-q-progress, bb-q-progress-fill, bb-q-controls, bb-q-back, bb-q-restart, bb-q-close, bb-q-logo |
| Screens | bb-q-screen, with bb-q-screen--start, --question, --interstitial, --pre-result or --result; bb-q-template wraps a screen your template renders |
| Start page | bb-q-start, bb-q-start-image, bb-q-start-title, bb-q-start-description, bb-q-start-button |
| Question | bb-q-question, bb-q-question-title, bb-q-question-description, bb-q-question-image |
| Answers | bb-q-answers, bb-q-answer, bb-q-answer-text, bb-q-answer-description, bb-q-answer-image, bb-q-answer-check |
| Inputs | bb-q-field, bb-q-field-label, bb-q-input, bb-q-slider, bb-q-phone, bb-q-dropdown, bb-q-dropdown-list, bb-q-dropdown-option, bb-q-consent, bb-q-field-error |
| Buttons | bb-q-footer, bb-q-next, bb-q-skip, bb-q-error |
| Loading and pre-result | bb-q-loading, bb-q-loading-dots, bb-q-pre-result, bb-q-pre-result-image, bb-q-pre-result-title, bb-q-pre-result-description |
| Result page | bb-q-result, bb-q-result-title, bb-q-result-description, bb-q-result-list, bb-q-result-card, bb-q-result-card-image, bb-q-result-card-label, bb-q-result-card-name, bb-q-result-card-price, bb-q-result-card-button, bb-q-result-add, bb-q-result-error, bb-q-result-retry |
| Product check page | bb-q-check (with data-state="match" or "no-match"), bb-q-check-title, bb-q-check-description, bb-q-check-label, bb-q-check-product, bb-q-check-alternatives |
The question screen also has data-bb-display-type, such as standard, picture or dropdown, so you can style one question type on its own. The product check page uses the result card classes for its cards, and the bb-q-check classes on top, for example:
.bb-q-check[data-state="no-match"] .bb-q-check-product { opacity: .6; }
.bb-q-check-label[data-active] { text-transform: uppercase; }How templates work
- Templates are Handlebars:
{{title}}prints a value, and you can use{{#if}},{{#each}}and the helperseq,ne,or,and,incandlookup. Every value is escaped. - You tell bluebarry what an element does with a
data-bb-attribute, such asdata-bb-startordata-bb-answer. bluebarry then wires the behavior to your element. - Your markup has no styling until your CSS styles it. The one exception is the start button and the Next button: they start in the theme's button colors, radius and font, and any rule of yours wins.
- Put all CSS in the CSS tab. A
<style>element in a template is not allowed.
Start page
You can use title, description, buttonText, imageUrl, logoUrl, questionCount and language. The template needs a button or link with data-bb-start, which starts the quiz.
<div class="hero">
{{#if imageUrl}}<img src="{{imageUrl}}" alt="">{{/if}}
<h1>{{title}}</h1>
<p>{{description}}</p>
<button type="button" data-bb-start>{{buttonText}}</button>
</div>Question
The question template is used for every question, whatever its type. Pages you add between questions keep their own layout. You can use title, description, imageUrl, displayType, isMultipleChoice, step (the question number in the shopper's path), progress (0 to 100), nextText, skipText, logoUrl and language, plus the lists below.
The template needs one empty element with data-bb-answers. Whatever your template does not render itself, bluebarry puts there: the answers, the dropdown, the input fields, the consent checkbox and error messages. Add an empty element with data-bb-actions to decide where the Next and Skip buttons go.
Your own answers
Loop over answers and render each answer as a button with data-bb-answer. Each answer has answerId, text, description, imageUrl and index. Render all answers or none, and keep links, inputs and other buttons out of the answer button.
{{#each answers}}
<button type="button" class="choice" data-bb-answer="{{answerId}}">
{{#if imageUrl}}<img src="{{imageUrl}}" alt="">{{/if}}
<span>{{text}}</span>
</button>
{{/each}}
<div data-bb-answers></div>bluebarry adds bb-q-answer to your buttons, sets data-selected on a selected answer and handles single and multi-select. A dropdown question has its options in options instead. Without your own buttons it keeps the built-in dropdown with its search.
Input fields and consent
Text, email, phone, number, slider and name questions have their inputs in fields, each with answerId, kind, label, placeholder and required. Put data-bb-field on an <input> for each field. bluebarry sets the input type, checks the value and writes a message into an empty element with data-bb-field-error.
For an email or phone question with a consent line, add a checkbox with data-bb-consent and an empty element with data-bb-consent-text. bluebarry writes your consent text there, so shoppers always read the exact wording they agree to.
{{#each fields}}
<label>{{label}} <input data-bb-field="{{answerId}}" placeholder="{{placeholder}}"></label>
<span class="hint" data-bb-field-error="{{answerId}}"></span>
{{/each}}
{{#if hasConsent}}
<label><input type="checkbox" data-bb-consent> <span data-bb-consent-text></span></label>
{{/if}}
<div data-bb-answers></div>Next, Skip and Back
<button data-bb-next>{{nextText}}</button>and<button data-bb-skip>{{skipText}}</button>work like the built-in buttons. bluebarry keeps Next disabled until the answer is valid and hides a button where the question has none. The footer then only shows the buttons your template leaves out.data-bb-back,data-bb-restartanddata-bb-closeon your own button go back, restart the quiz or close it.- A question template with a
data-bb-backbutton owns the top bar. The quiz then hides its own progress bar, Back, Restart and logo on question screens, and only the Close button stays. Draw your own progress from{{progress}}or{{step}}.
Loading and pre-result
The loading template shows while the results load, while a shopper picks up a quiz where they left off and while a screen's code loads, so keep its text general. You can use label, logoUrl and language. label is always in English, so pick visible text based on language or keep the screen decorative. The pre-result template shows while the results are prepared, with the title, description and imageUrl of the quiz's pre-result page. Both screens move on by themselves, so they take no data-bb- attributes.
<div class="spinner" aria-hidden="true"></div>
{{#if logoUrl}}<img src="{{logoUrl}}" alt="">{{/if}}Product check page
When a quiz runs from a product page, its result is the product check page: is this product a match? The Product check template replaces that page. It works like a custom result page (beta), with the same product fields, helpers and buttons. On top of that you get product (the checked product), products (the alternatives), match, title and description, plus labelOne and labelTwo for the labels over the checked product and the alternatives. Those two are not plain text: print {{labelOne.text}} and check labelOne.active for the highlighted one. The texts come from the product check settings of the quiz.
<h2>{{title}}</h2>
{{#with product}}
<h3>{{name}}</h3>
{{#if addsToCart}}<button type="button" data-bb-add="{{variantId}}">{{cta}}</button>
{{else}}<a href="{{url}}" data-bb-product-link="{{url}}">{{cta}}</a>{{/if}}
{{/with}}The template needs at least one data-bb-add or data-bb-product-link button or link, so the shopper can always buy. The page has no next step, so data-bb-next, data-bb-add-all and data-bb-ask-chat are not allowed. The CSS of a custom result page does not reach it: style it in the CSS tab.
The Close button
On the start page, on a question that owns the top bar and on a custom result page, the Close button floats in the top right corner, over your template. Keep that corner clear, for example with padding-right: 56px on your own top bar.
To place Close in your own layout instead, add one empty element with data-bb-close-slot to the start page or question template. The button there takes the text color of the element, so give it a color that stands out, and style it with [data-bb-close-slot] .bb-q-close. An embedded quiz has no Close button, so the slot stays empty there.
<header class="topbar">
<button type="button" data-bb-back>Back</button>
<span data-bb-close-slot></span>
</header>Screen transitions
To animate screen changes with your own CSS, open Animations in the quiz's Design tab and pick Custom for desktop, mobile or both. During a screen change both screens are on the page:
- The screen going out gets
data-bb-transition="leave"and the one coming indata-bb-transition="enter". Both getdata-bb-direction:forward, orbackafter Back. - Every screen has
data-bb-screen(start,question,loading,pre-result,result,product-checkand so on), so one screen can move differently. - The quiz waits until your animations end, at most 1.2 seconds. Use
@keyframesrather thantransition, and keep them under half a second. - For shoppers who turn on reduced motion, screens swap at once. Without CSS for these attributes, screens change instantly too.
@keyframes brand-in { from { opacity: 0; transform: translateY(24px); } }
@keyframes brand-out { to { opacity: 0; transform: translateY(-12px); } }
[data-bb-transition="enter"] { animation: brand-in .35s ease-out both; }
[data-bb-transition="leave"] { animation: brand-out .2s ease-in both; }
@keyframes brand-in-back { from { opacity: 0; transform: translateY(-24px); } }
[data-bb-transition="enter"][data-bb-direction="back"] { animation-name: brand-in-back; }Scripts
Every template can hold an inline <script>. It runs in the live quiz and in the preview in Custom code. Use the data-bb- attributes for everything they cover, and script only what markup cannot do, such as a live summary of the choices. Scripts with src or type="module" are not allowed.
bluebarryQuiz(document.currentScript) gives your script the current screen:
getState()returns the screen, the question, its answers and what is selected, the field values, the consent, and whether the shopper can go next, skip or back.- Actions do exactly what the matching click does:
select(id),deselect(id),toggle(id),setField(id, value),setConsent(checked),next(),skip(),back(),restart(),close()andstart(). They returnfalsewhen the quiz does not take them, for examplenext()before the answer is valid. on(type, listener)listens to the screen's events:screen,select,answer,change,validationand, with the Custom animation,transition. Read the state in achangelistener, because it updates once the screen has rendered. A script in the loading template runs, but gets no events.
{{#each answers}}<button type="button" data-bb-answer="{{answerId}}">{{text}}</button>{{/each}}
<p class="summary" aria-live="polite"></p>
<div data-bb-answers></div>
<script>
const quiz = bluebarryQuiz(document.currentScript);
const summary = document.currentScript.closest('.bb-q-template').querySelector('.summary');
const show = (state) => {
const picked = state.answers.filter((a) => a.selected).map((a) => a.text);
summary.textContent = picked.length ? 'Your picks: ' + picked.join(', ') : '';
};
show(quiz.getState());
quiz.on('change', (detail) => show(detail.state));
</script>Each screen gets its own handle, and it stops when the screen goes away. Listen through on or on the template rather than on document, or your listeners pile up across questions.
When a screen falls back
The editor refuses a template that misses a required part, such as a start page without data-bb-start or a question template without one empty data-bb-answers. Some problems only show up for a certain question, for example when the answers slot sits inside an {{#if}}, when your answer buttons do not match the question's answers one to one, or when a template has a consent checkbox on a question without a consent line. That screen then shows the built-in layout and the browser console gets a warning. The shopper can always finish the quiz.
Editing text on custom screens
Where Studio shows a quiz in its custom design on a canvas, such as on Home, you cannot click the text of a screen your template lays out to edit it. Your template decides where each text goes, and it can repeat a text, leave it out or change it with a script, so Studio cannot tie what you click to a setting of the quiz. Change the texts in the quiz editor and the layout in Custom code. The canvas in the quiz editor keeps the built-in layout, so its texts stay editable there. Use the preview in Custom code or Preview to see your design.
Rules and limits
- The CSS can be up to 40,000 characters and each template up to 60,000.
- CSS that hides a control shoppers need, such as the answers, the Next button or the Close button, with
display: noneorvisibility: hiddenis refused. @keyframesnames the quiz uses itself, such asspin,pulseor names that start withadvisor-, are refused. Pick a name of your own, such asbrand-fade.@importis removed when the theme saves.
Good to know
- The code belongs to the theme, so it changes every quiz that uses the theme. It is not part of a quiz version: you do not publish it. The preview shows changes right away, and live quizzes pick them up within about an hour. To try something on one quiz only, duplicate the theme first. See Customize the quiz theme and layout.
- Once a theme has custom code, the header bar above the quiz turns transparent so your background runs to the top. Give
.bb-q-header-bara background for a solid bar. - On the first load, a templated start page or question shows the theme's background for a moment while the template code loads.
- Custom code works the same on Shopify, WooCommerce, Magento and CCV Shop, because the quiz runs in its own frame on every platform.