Theme customizations using ShipScout data

The definitive guide to updating shipping related copy and UI throughout your shop


As you design your test, it's critical that you update the places in your shop that mention your shipping rate. Here's a list of places that merchants typically show shipping rate information:

  • Top announcement banner

  • Upsell modal

  • Product detail page

  • Cart and cart drawer

  • Shipping policy page

  • FAQ

Depending on the implementation of the copy or UI element, your approach to update it may differ. We offer two different ways to update your theme. Our goal is make it as easy as possible for you to make sure your customers see the right shipping information.

Please give us feedback at on how we can improve our developer SDK.

Using liquid

If your copy and/or variables are primarily set in your theme, this is the best method for updating it.

Step 1 - update the places that refer to the shipping threshold value

In liquid, you can access the shipping rate threshold value from the cart object in liquid. This value will be updated to reflect the correct thresholdValue for the given user.

Here's a example code snippet that checks for the shipscout threshold value and has a default value in case that is not set. This pattern is great to ensure that uninstalling ShipScout doesn't impact the shop.

Step 2 - Dynamically re-render sections using this variable after the variant data changes

When a customer visits your store for the first time, ShipScout will assign a variant to the customer after the page loads via javascript. This happens after the liquid page gets rendered. Since on this first page load, the liquid page was rendered based on no variant, the threshold value won't necessarily match the variant threshold value.

To dynamically render sections, add this code to the <head /> of your shop:

  window._shipScout = window._shipScout || [];
  _shipScout.push(async function (response) {
      // Only update section if assignment data is new
      if (response.isNewAssignment) {
          // Update header using shopify Section API
          const announcementBarID = "announcement_bar_section_id";
          let announcementBarHTML = await (await fetch(`?section_id=${announcementBarID}}`)).text();
          document.getElementById('announcement-bar').innerHTML = announcementBarHTML;

          // Update cart using shopify Section API
          const cartID = "cart"
          let header = await (await fetch(`?cart=${cartID}}`)).text()
          document.getElementById('cart').innerHTML = header

          // ...etc

Using Javascript

If the area you're trying to update cannot be updated via liquid because it is rendered via javascript or by a different app, you can use our Javascript API to drive it.

Include the following JavaScript wherever you'd like (we recommend somewhere before the closing </head> tag). It will execute as soon as ShipScout has loaded and will inform you on which test the current user is in.

window._shipScout = window._shipScout || [];
_shipScout.push(function (response) {

        example response object
            testId: 1,
            testType: 'threshold',
            variant: 'B',
            threshold: true,
            thresholdCents: 5000,
            thresholdMetRateAmountCents: 0,
            shippingPriceCents: 1000,
            lineItemProperty: 0467e6f7-8d66-4610-a939-da76dd9f7a68_1_B,
            isNewAssignment: false
    //apply any exchange rates to currency if necessary
    var thresholdCents = (window.Shopify && Shopify.currency && Shopify.currency.rate) ? response.freeShippingThresholdCents * Shopify.currency.rate : response.freeShippingThresholdCents;
    var flatrateCents = (window.Shopify && Shopify.currency && Shopify.currency.rate) ? response.shippingPriceCents * Shopify.currency.rate : response.shippingPriceCents;

    //format currency
    var currencyFormat = ShipScoutGetCurrency();
    //get threshold amount with currency symbol
    var thresholdAmount = ShipScoutFormatMoney(thresholdCents, currencyFormat);

    //get flat rate amount with currency symbol
    var flatrateAmount = ShipScoutFormatMoney(flatrateCents, currencyFormat);

    //==== insert your code below to dynamically update elements ====//

    //example updating an element on the page dynamically with the threshold amount
    var el = document.getElementById("foo-bar");
    if(response.freeShippingThresholdCents === 0) {
        el.innerHTML = "FREE!";
    } else {
        el.innerHTML = thresholdAmount;

Here's a description of the properties and values to expect in the response object.


Value Type




integer | null


The test number.


string | null


The variant this user is in.




Only present if threshold is true.

The amount, in cents, required to get the threshold rate.


integer | null


Only present if threshold is true. The shipping price, in cents, if threshold amount is met




The price, in cents, of shipping.




If there's a free shipping threshold for this user.


string | null


The value can either be "threshold", "flat-rate" or "new-vs-returning".




True if this is the shipscout response data changed within this page load. Useful for optimizing expensive effects.

If there's no test live but you do have a Default Shipping Rate set in ShipScout the rate settings will still be returned by the JS SDK. The following 3 properties will be null however: testId, testType, and variant.

You can append ?shipscout_preview=yes to any URL on your website to test your SDK integration without a live test. Appending this URL will simulate these hard-coded values for the SDK:

testType: 'threshold',
threshold: true,
freeShippingThresholdCents: 0,
testId: 'preview',
variant: 'A',
shippingPriceCents: 500,
isNewAssignment: true

If you need to overwrite these hard-coded preview values to simulate a different setup or variant you can do that like this:

window._shipScout = window._shipScout || [];
_shipScout.push(function (response) {

   //Temporarily overwrite the response for testing
   response = {
      freeShippingThresholdCents: 5000,
      variant: 'B',


Last updated