Gift Wrap Checkbox
A paid gift wrap add-on with an optional gift message, right above add to cart.
A lifestyle photo next to the products in it, each with its own add to cart button.
Important: Before making any changes to your theme, duplicate it in Online Store > Themes so you have a backup.
Shoppers buy outfits, rooms and setups, not single products. Complete the look pairs a lifestyle photo with the products in it so shoppers can add the rest of the look in a tap. Products with options link to their own page so the shopper can pick a size or colour.
Complete the look
Everything in this photo, ready to add in one tap.
Preview with the default settings. Colours, text and layout can all be changed in the theme editor.
In Shopify admin go to Online Store > Themes. Next to the theme you want to edit, click the three dots and choose Edit code.
In the Sections folder click Add a new section, name it lt-complete-the-look, delete the placeholder code, paste in the code below and click Save.
Click Customize, go to Products > Default product (or the Home page), click Add section and choose Complete the look.
Change the settings in the sidebar, drag the section where you want it, and click Save.
{%- comment -%}
Complete the look by LAUNCHTIP
https://launchtip.com/free-shopify-sections-code
{%- endcomment -%}
{%- style -%}
#lt-{{ section.id }} { padding: {{ section.settings.padding }}px 0; }
#lt-{{ section.id }} .lt-ctl { display: grid; gap: 32px; align-items: center; }
@media (min-width: 750px) {
#lt-{{ section.id }} .lt-ctl { grid-template-columns: 1fr 1fr; }
#lt-{{ section.id }} .lt-ctl--image-right .lt-ctl__image { order: 2; }
}
#lt-{{ section.id }} .lt-ctl__image img { width: 100%; height: auto; border-radius: 10px; display: block; }
#lt-{{ section.id }} .lt-ctl__heading { margin: 0 0 6px; }
#lt-{{ section.id }} .lt-ctl__text { margin: 0 0 18px; opacity: 0.8; }
#lt-{{ section.id }} .lt-ctl__item { display: flex; align-items: center; gap: 14px; padding: 12px 0; border-top: 1px solid {{ section.settings.border_color }}; }
#lt-{{ section.id }} .lt-ctl__item img { width: 64px; height: 64px; object-fit: cover; border-radius: 6px; flex-shrink: 0; }
#lt-{{ section.id }} .lt-ctl__name { flex: 1; min-width: 0; }
#lt-{{ section.id }} .lt-ctl__name a { color: inherit; text-decoration: none; display: block; }
#lt-{{ section.id }} .lt-ctl__price { font-size: 0.9em; opacity: 0.75; }
#lt-{{ section.id }} .lt-ctl__add { background: {{ section.settings.button_color }}; color: {{ section.settings.button_text }}; border: 0; border-radius: 6px; padding: 10px 16px; font: inherit; font-size: 0.9em; font-weight: 600; cursor: pointer; text-decoration: none; white-space: nowrap; }
#lt-{{ section.id }} .lt-ctl__add[disabled] { opacity: 0.6; cursor: default; }
{%- endstyle -%}
<div
id="lt-{{ section.id }}"
class="page-width"
data-add-url="{{ routes.cart_add_url }}.js"
data-added="{{ section.settings.added_label | escape }}"
>
<div class="lt-ctl{% if section.settings.image_position == 'right' %} lt-ctl--image-right{% endif %}">
<div class="lt-ctl__image">
{%- if section.settings.image != blank -%}
{{ section.settings.image | image_url: width: 1200 | image_tag: loading: 'lazy', sizes: '(min-width: 750px) 50vw, 100vw', widths: '400, 600, 800, 1200' }}
{%- else -%}
{{ 'lifestyle-1' | placeholder_svg_tag }}
{%- endif -%}
</div>
<div>
{%- if section.settings.heading != blank -%}
<h2 class="lt-ctl__heading h2">{{ section.settings.heading }}</h2>
{%- endif -%}
{%- if section.settings.text != blank -%}
<p class="lt-ctl__text">{{ section.settings.text }}</p>
{%- endif -%}
{%- for p in section.settings.products -%}
{%- assign v = p.selected_or_first_available_variant -%}
<div class="lt-ctl__item">
{%- if p.featured_image != blank -%}
{{ p.featured_image | image_url: width: 160 | image_tag: loading: 'lazy', alt: p.title }}
{%- endif -%}
<div class="lt-ctl__name">
<a href="{{ p.url }}">{{ p.title }}</a>
<span class="lt-ctl__price">{{ v.price | money }}</span>
</div>
{%- if p.has_only_default_variant and v.available -%}
<button type="button" class="lt-ctl__add" data-id="{{ v.id }}">{{ section.settings.button_label }}</button>
{%- elsif v.available -%}
<a class="lt-ctl__add" href="{{ p.url }}">{{ section.settings.options_label }}</a>
{%- else -%}
<button type="button" class="lt-ctl__add" disabled>{{ section.settings.sold_out_label }}</button>
{%- endif -%}
</div>
{%- else -%}
{%- if request.design_mode -%}<p>Pick the products in this look in the section settings.</p>{%- endif -%}
{%- endfor -%}
</div>
</div>
</div>
<script>
(function () {
var root = document.getElementById('lt-{{ section.id }}');
if (!root || root.dataset.ready) return;
root.dataset.ready = '1';
root.addEventListener('click', function (event) {
var button = event.target.closest('button[data-id]');
if (!button || button.disabled) return;
var label = button.textContent;
button.disabled = true;
fetch(root.dataset.addUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
body: JSON.stringify({ items: [{ id: Number(button.dataset.id), quantity: 1 }] })
})
.then(function (response) {
if (!response.ok) throw new Error('add failed');
button.textContent = root.dataset.added;
document.dispatchEvent(new CustomEvent('cart:refresh', { bubbles: true }));
setTimeout(function () { button.textContent = label; button.disabled = false; }, 2500);
})
.catch(function () { button.textContent = label; button.disabled = false; });
});
})();
</script>
{% schema %}
{
"name": "Complete the look",
"tag": "section",
"class": "lt-ctl-section",
"settings": [
{
"type": "image_picker",
"id": "image",
"label": "Look image"
},
{
"type": "select",
"id": "image_position",
"label": "Image position",
"options": [
{ "value": "left", "label": "Left" },
{ "value": "right", "label": "Right" }
],
"default": "left"
},
{
"type": "text",
"id": "heading",
"label": "Heading",
"default": "Complete the look"
},
{
"type": "textarea",
"id": "text",
"label": "Text",
"default": "Everything in this photo, ready to add in one tap."
},
{
"type": "product_list",
"id": "products",
"label": "Products in the look",
"limit": 6
},
{
"type": "text",
"id": "button_label",
"label": "Add button label",
"default": "Add"
},
{
"type": "text",
"id": "added_label",
"label": "Added label",
"default": "Added"
},
{
"type": "text",
"id": "options_label",
"label": "Label for products with options",
"default": "Choose options"
},
{
"type": "text",
"id": "sold_out_label",
"label": "Sold out label",
"default": "Sold out"
},
{
"type": "color",
"id": "button_color",
"label": "Button colour",
"default": "#111111"
},
{
"type": "color",
"id": "button_text",
"label": "Button text colour",
"default": "#ffffff"
},
{
"type": "color",
"id": "border_color",
"label": "Divider colour",
"default": "#e5e5e5"
},
{
"type": "range",
"id": "padding",
"label": "Vertical padding",
"min": 0,
"max": 100,
"step": 4,
"unit": "px",
"default": 40
}
],
"presets": [
{
"name": "Complete the look"
}
]
}
{% endschema %}
| Setting | Default |
|---|---|
| Look image | — |
| Image position | Left |
| Heading | Complete the look |
| Text | Everything in this photo, ready to add in one tap. |
| Products in the look | — |
| Add button label | Add |
| Added label | Added |
| Label for products with options | Choose options |
| Sold out label | Sold out |
| Button colour | #111111 |
| Button text colour | #ffffff |
| Divider colour | #e5e5e5 |
| Vertical padding | 40px |
Further reading: Best upsell apps for Shopify
Up to six per section. Add the section twice for a second look.
The button confirms with Added and asks your theme to refresh the cart. Themes that listen for that event update the cart count straight away.
The section uses an image picker. Swap it for a video setting if you want motion, but keep the products visible in the first frame.
SellUp recommends the next item on every product page and in the cart, matched to your theme, without you hand-picking each look.
Try SellUpA paid gift wrap add-on with an optional gift message, right above add to cart.
Hand-picked product bundles with checkboxes, a running total and one add-all button.
"You're £12 away from free shipping" with a bar that fills as the cart grows.
Discover more code snippets to enhance your Shopify store.
View All Sections