Shopify Redirect Changes

This article describes possible approaches that can be made to adjust the Shopify Redirect Script to track subscription details on products and to pass data from ad link to CC checkout.

The instructions below may not work with your specific theme. If you are having issues getting these to work, please submit a support ticket for our team to investigate. Include the name of your store.

  • Affiliate String Tracking

  • UTM Tracking

  • Subscription Details Tracking

  • 50/50 Split

  • Clear Cart After Redirect

  • Quantity Updates

  • Redirect to multiple checkouts, based on value in URL

  • Redirect with a custom item value


Affiliate String Tracking

  • Add the following script to your theme.liquid file

  
<script>
const urlSearchParams = new URLSearchParams(window.location.search);
document.cookie = urlSearchParams;
</script>
  

This takes the data on the query string when customer lands on your site initially and then saves it to a cookie in that session. This cookie will be retrieved later and sent along on redirect.

To track details properly you must form your tracking string using the format in Checkout Champ specific for that affiliate.

example: https://mysite.myshopify.com?affId=0029B642
  • In the redirect script replace the getCheckoutURLfunction with the following

function getCheckoutURL(products) {
         cookie = getCartCookie('cart');
         affId = getCartCookie('?affId');
        coupon = '&couponCode={{cart.cart_level_discount_applications[0].title}}';
        console.log(affId,'affId');
        var urlLineItems = Object.keys(products).reduce(function (output, productId) {
          var quantity = products[productId];
          return output.concat([ productId + ':' + quantity ]);
        }, []).join(';');

        if (typeof affId !== 'undefined')
        	return self.options.checkoutUrl + '?products=' + urlLineItems + '&cartId='+cookie + '&affId='+affId+coupon;
        else
          return self.options.checkoutUrl + '?products=' + urlLineItems + '&cartId='+cookie+coupon;
      }

The main difference in this new function is that it’ll attempt to retrieve the cookie data related to affiliate info. This new function will also attempt to include any discounts applied to the cart (limit 1 at this time) in the redirect. This will allow for the consumer to see the same discounted price in both systems, reducing the likelihood of an abandoned cart. The coupon code must exist in Checkout Champ for a discount to be applied. If the details can be retrieved they will be appended to the end of the redirect link, if not, the redirect will occur without these details.


UTM Tracking

  • Add the following script to your theme.liquid file (this is already complete if you have implemented Affiliate Tracking above)

  
<script>
const urlSearchParams = new URLSearchParams(window.location.search);
document.cookie = urlSearchParams;
</script>
  

This takes the data on the query string when customer lands on your page initially and then saves it to a cookie in that session. This cookie will be retrieved later and sent along on redirect.

To track details properly you must form your tracking string using this standard utm syntax (you can use up to all 5 utm values, this example only shows 2).

example: https://mysite.myshopify.com?utm_campaign=1&utm_medium=test
  • In the redirect script replace the getCheckoutURLfunction with the following

function getCheckoutURL(products) {
         cookie = getCartCookie('cart');
         utm = getCartCookie('?_shopify_sa_p');
        coupon = '&couponCode={{cart.cart_level_discount_applications[0].title}}';
        console.log(decodeURIComponent(utm),'utm');
        var urlLineItems = Object.keys(products).reduce(function (output, productId) {
          var quantity = products[productId];
          return output.concat([ productId + ':' + quantity ]);
        }, []).join(';');

        if (typeof utm !== 'undefined')
        	return self.options.checkoutUrl + '?products=' + urlLineItems + '&cartId='+cookie + '&'+decodeURIComponent(utm)+coupon;
        else
          return self.options.checkoutUrl + '?products=' + urlLineItems + '&cartId='+cookie+coupon;
      }

The main difference in this new function is that it’ll attempt to retrieve the cookie data related to affiliate info. This new function will also attempt to include any discounts applied to the cart (limit 1 at this time) in the redirect. This will allow for a consumer to see the same discounted price in both systems, reducing the likelihood of an abandoned cart. The coupon code must exist in Checkout Champ for a discount to be applied. If the details can be retrieved they will be appended to the end of the redirect link, if not, the redirect will occur without these details.


Subscription Details Tracking

  • If you offer subscribe and save options on your products you can capture the details selected by the customer and have it included on the redirect string so that Checkout Champ knows the frequency to which to bill.

  • Replace the productIdsWithQuantitiesfunction with the following

  function productIdsWithQuantities() {
        {%- assign added_first = false -%}
        return {
          {%- for item in cart.items -%}
            {%- if item.variant.metafields.productId.productId -%}
          {%- if added_first %},{% endif -%}
           {%- if item.selling_plan_allocation -%}
          "{{ item.variant.metafields.productId.productId}}{{"|"}}{{item.selling_plan_allocation.selling_plan.name | url_encode}}": {{ item.quantity | json }}
          {%- else -%}
           "{{ item.variant.metafields.productId.productId }}": {{ item.quantity | json }}
          {% endif -%}
              {%- assign added_first = true -%}
            
          {%- endif -%}
          
          {%- endfor -%}
        };
      }   
      

The main difference in this new function is that it’ll attempt to read the selling plan associated with each product in the cart, if a customer selected a subscribe and save option a selling plan should be associated with the product and those details will be sent along on the redirect string.


50/50 Split

  • If you want to test the redirect you can split your traffic between Shopify and Checkout Champ checkouts.

  • Replace the inject function with the following

 function inject() {
        {%- assign min = 1 -%}
        {%- assign max = 100 -%}
        {%- assign diff = max | minus: min -%}
        {%- assign random_number = "now" | date: "%N" | modulo: diff | plus: min -%}
        var random_number = {{random_number}};
        if(random_number < 50)
        {
          debug('Inject');
          self.$checkoutButton.on('click', checkout);
        }

      }
      

The main difference in this new function is that it’ll only redirect out of Shopify if the random_number generated is < 50. The min/max values can be changed to any value client would like.


Clear Cart After Redirect

  • If you want to prevent customers from navigating back to your Shopify store with a full cart then replace the existing checkout function with the following

function checkout(event) {
        var checkoutUrl = getCheckoutURL(self.options.products);
        debug('Checkout ->', checkoutUrl);
        event.preventDefault();
         var xhrClearCart = new XMLHttpRequest();
          xhrClearCart.open('POST', '/cart/clear.js', true);
          xhrClearCart.send();  
        window.location.href = checkoutUrl;
      }

Quantity Updates

  • Many Shopify themes do not properly pass the quantity to the checkout page when a consumer goes to checkout, returns to the shopping cart, and adjusts the quantity. The following code has been effective solving this issue on some themes.

  • In the [store]-cart.js.liquid file

    <script>
    $(document).ready(function(){
      $("#your-shopping-cart .qty-adjust,.cart__product-remove").click(function(){
      setTimeout(()=>{
       window.location.reload();
      },1000)
    
      });
    });
    </script>

Redirect to multiple checkouts, based on value in URL

function getCheckoutURL(products) {
         cookie = getCartCookie('cart');
         affId = getCartCookie('?affId');
        coupon = '&couponCode={{cart.cart_level_discount_applications[0].title}}';
        console.log(affId,'affId');
        var urlLineItems = Object.keys(products).reduce(function (output, productId) 
{
          var quantity = products[productId];
          return output.concat([ productId + ':' + quantity ]);
        }, []).join(';');

        var searchParams = new URLSearchParams(window.location.search);
        var checkoutURL = '[ENTER-CHECKOUT-URL1-HERE]';
        console.log(searchParams);
        if(searchParams.has('ct'))
        {
          var param = searchParams.get('ct');
          console.log(param);
          if(param == 'subprice')
          {
            var checkoutURL = '[ENTER-CHECKOUT-URL2-HERE]';
          }
        }
        if (typeof affId !== 'undefined')
        	return checkoutURL + '?products=' + urlLineItems + '&cartId='+cookie + '&affId='+affId+coupon;
        else
          return checkoutURL + '?products=' + urlLineItems + '&cartId='+cookie+coupon;
      }

Redirect with a custom item value

  • The standard function to build the products parameter can be modified to pass a custom value for each item. It searches through the item properties to find the needed values. This is a good starting point, but likely needs adjustment to match your theme and business needs.

  • The return value looks similar to this: products=137||customization~John Doe:1

function productIdsWithQuantities() {
    {%- assign added_first = false -%}
    return {
      {%- for item in cart.items -%}
        {%- assign property_size = item.properties | size -%}
        {% if property_size > 0 %}
          {%- capture prdctOptions -%}
            {% for p in item.properties %}
              {% unless p.last == blank %}{{ p.first }}~{% if p.last contains '/uploads/' %}{{ p.last | split: '/' | last }}{% else %}{{ p.last }}{% endif %}{% unless forloop.last %}|{% endunless -%}
              {% endunless %}
            {% endfor %}
          {%- endcapture %}
          {%- assign prdctOptionForUrl = prdctOptions | newline_to_br | split: '<br />' -%}
          {%- capture stripedPrdctOptions -%}
            {% for pOption in prdctOptionForUrl -%}
                {{ pOption | strip | strip_newlines | url_encode  }}
            {%- endfor %}
          {%- endcapture %}
        {% endif %} 
        {%- if item.variant.metafields.productId.productId -%}
      {%- if added_first %},{% endif -%}
        {%- if item.selling_plan_allocation -%}
          {% if property_size > 0 %}
            "{{ item.variant.metafields.productId.productId}}{{"|"}}{{item.selling_plan_allocation.selling_plan.name | url_encode}}{{ "|" }}{{ stripedPrdctOptions | strip_newlines }}": {{ item.quantity | json }}
          {% else %}
            "{{ item.variant.metafields.productId.productId}}{{"|"}}{{item.selling_plan_allocation.selling_plan.name | url_encode}}": {{ item.quantity | json }}
          {% endif %}
      {%- else -%}
          {% if property_size > 0 %}
            "{{ item.variant.metafields.productId.productId }}{{ "|" }}{{ "|" }}{{ stripedPrdctOptions | strip_newlines }}": {{ item.quantity | json }}
          {% else %}
            "{{ item.variant.metafields.productId.productId }}": {{ item.quantity | json }}
          {% endif %}
      {% endif -%}
          {%- assign added_first = true -%}
        
      {%- endif -%}
      
      {%- endfor -%}
    };
  }