free shipping progress bar Martin Supplieth

Integrating a Free Shipping Progress Bar in Shopware 6: A Step-by-Step Guide

Introduction: Why a Free Shipping Progress Bar?

Free shipping is the holy grail for many online shoppers. But how do you leverage it effectively? With a free shipping progress bar, you clearly show customers how close they are to qualifying for free shipping – a great incentive to add more items to their cart. In this guide, you'll learn step-by-step how to integrate this progress bar into Shopware 6.

Benefits: How Does the Progress Bar Boost Your Average Order Value?

  • Increased Average Order Value: Encouraging customers to add more items to qualify for free shipping directly boosts your sales.
  • Better Customer Experience: Clear, transparent information builds trust and enhances satisfaction.
  • Reduced Abandonment Rate: Customers quickly see how close they are to free shipping, reducing cart abandonment.
  • Targeted Upselling: Promote relevant products to make reaching the free shipping threshold even more enticing.

Preparation: Before You Begin

Make sure you have the following ready:

  • A Shopware 6 shop
  • A test environment (so your live shop isn’t affected)
  • A child theme
  • Access to your template files

Everything ready? Let's get started!

4-Step Guide

Step 1: Configure the Shipping Method

For the progress bar to work correctly, you first need to configure the appropriate shipping method.

Settings → Shop → Shipping (Source: Shopware 6.6.9.0 Admin Area)

  1. Go to Settings > Shop > Shipping.
  2. Click on the shipping method "Standard" (or another if you've renamed it).
  3. Under "Price Rules" create two rules:
    • $0 to $60: Shipping cost $4.95 (gross)
    • $60 to ∞: Shipping cost $0 (i.e., free)
  4. In the "Price Matrix" section, specify that the rule is based on the cart total.
  5. Save your settings.

Defining Price Rules (Source: Shopware 6.6.9.0 Admin Area)

With this setup, your progress bar will access the correct value and accurately display when shipping becomes free.

Step 2: Create Translation Files

For multilingual support: Create JSON files for translations.

File: YourTheme.de-DE.json

{
  "freeShippingProgress": {
    "heading": "Progress Toward Free Shipping",
    "only": "Only",
    "moreToFreeShipping": "more until free shipping",
    "freeShippingInfo": "Free shipping within the USA.",
    "freeShippingAvailable": "Congratulations! You qualify for free shipping within the USA."
  }
}
German Translation File

File: YourTheme.en-GB.json

{
  "freeShippingProgress": {
    "heading": "Free Shipping Progress",
    "only": "Only",
    "moreToFreeShipping": "more to get free shipping",
    "freeShippingInfo": "Free shipping within the USA.",
    "freeShippingAvailable": "Congratulations! You qualify for free shipping within the USA."
  }
}
English Translation File

Save the files under custom/plugins/YourTheme/src/Resources/snippet/.

Step 3: Edit the Twig File

Create or extend the offcanvas-cart.html.twig file in your child theme:

{% sw_extends '@Storefront/storefront/component/checkout/offcanvas-cart.html.twig' %}

{% block component_offcanvas_cart_header %}
    {{ parent() }}
    {% block component_offcanvas_cart_header_free_shipping_progress %}
        {% set delivery = page.cart.deliveries.first %}
        {% if delivery is defined and delivery.shippingMethod is defined and delivery.shippingMethod.prices|length > 0 %}
            {% set shippingMethodPrice = delivery.shippingMethod.prices.first %}
            {% set freeShippingMinimum = shippingMethodPrice.quantityEnd ?? 0 %}
            {% set currentTotalWithoutShipping = page.cart.price.positionPrice %}

            {% if currentTotalWithoutShipping >= 0 and freeShippingMinimum > 0 %}
                {% set amountUntilFreeShipping = freeShippingMinimum - currentTotalWithoutShipping %}
                {% set progress = (currentTotalWithoutShipping / freeShippingMinimum) * 100 %}
                {% set progress = progress > 100 ? 100 : (progress < 0 ? 0 : progress) %}
                {% set cartToken = page.cart.token %}

                <div class="free-shipping-counter text-center mt-2"
                     aria-live="polite"
                     aria-labelledby="free-shipping-header-{{ cartToken }}">

                    <span id="free-shipping-header-{{ cartToken }}" class="visually-hidden">
                        {{ "freeShippingProgress.heading"|trans|sw_sanitize }}
                    </span>

                    {% if amountUntilFreeShipping > 0 %}
                        <p class="free-shipping-counter-text mb-2">
                            {{ "freeShippingProgress.only"|trans|sw_sanitize }}
                            <strong class="free-shipping-counter-amount">
                                {{ amountUntilFreeShipping|currency }}
                            </strong>
                            {{ "freeShippingProgress.moreToFreeShipping"|trans|sw_sanitize }}
                        </p> 
                        <div class="free-shipping-counter-range d-flex align-items-center justify-content-between">
                            <span class="free-shipping-counter-current-total">
                                {{ currentTotalWithoutShipping|currency }}
                            </span>
                            <div class="progress flex-grow-1 mx-2">
                                <div id="progress-bar-{{ cartToken }}"
                                     class="progress-bar progress-bar-striped progress-bar-animated"
                                     role="progressbar"
                                     style="width: {{ progress|round }}%;"
                                     aria-valuemin="0"
                                     aria-valuemax="100"
                                     aria-valuenow="{{ progress|round }}">
                                </div>
                            </div>
                            <span class="free-shipping-counter-minimum-total">
                                {{ freeShippingMinimum|currency }}
                            </span>
                        </div>
                        <p class="free-shipping-counter-info mt-2">
                            {{ "freeShippingProgress.freeShippingInfo"|trans|sw_sanitize }}
                        </p> 
                    {% else %}
                        <div class="free-shipping-counter-alert text-start">
                            {% sw_include '@Storefront/storefront/utilities/alert.html.twig' with {
                                type: 'success',
                                content: "freeShippingProgress.freeShippingAvailable"|trans|sw_sanitize
                            } %}
                        </div>
                    {% endif %}
                </div>
            {% endif %}
        {% endif %}
    {% endblock %}
{% endblock %}
Modified Twig File with Enhanced ARIA Attributes for Accessibility.

Step 4: Clear Cache & Compile Theme

  1. Clear Cache: Go to Settings > System > Cache & Indexes – click "Clear Caches"
  2. Compile Theme: Navigate to Content > Themes – select your theme and click "Save"

Conclusion

With this guide, you integrate a free shipping progress bar into your Shopware 6 shop. You boost your average order value, improve the user experience, and reduce cart abandonment. Always keep an eye on SEO, performance (e.g. clean code and fast load times), and accessibility (ARIA attributes, clear structure). If you have questions or need assistance, feel free to contact me. Good luck!

Important: This guide was tested on Shopware version 6.6.9.0. Follow these steps at your own risk. If your shop suddenly goes up in flames – I wasn’t responsible! 😉