Shopify
Overview
Follow the steps in this guide to integrate Zip into your Shopify store.
- Add the Payment Gateway
If you have any questions or need any support integrating, please email us.
Add The Payment Gateway
US
After successfully setting up Zip Connect (powered by Stripe) for your Zip account, you can add Zip as a payment option in your Shopify store.
- Install our Shopify Payments app, Zip (US):
- Click Install app to finish the installation.
- Click Connect to enable Zip (US).

- Click Install app to finish the installation.
Questions?
If you have have any questions, or encounter any issues when installing the app, please contact us at [email protected].
CA
After successfully setting up Zip Connect (powered by Stripe) for your Zip account, you can add Zip as a payment option in your Shopify store.
Install our Shopify Payments app, Zip (CA):
- Click Connect to enable Zip (CA).

Questions?
If you have have any questions, or encounter any issues when installing the app, please contact us at [email protected].
Widget Overview
What is the Zip Widget?
The Zip Widget is a visual price breakdown that appears on the product page, cart, and mini cart.
It is an easy way for your customers to understand Zip's benefits, how it works, and help inspire them to checkout. Our merchant partners with the Zip Widget on their product pages have shown that the widget can increase Conversion rate and Topline sales by more than 20%!
Read more here: Messaging & Widgets Overview
How do I Integrate the Widget?
To get the widget integrated in your Shopify store, please follow the Zip Widget App instructions.
If you require further customization, you can implement Zip's Classic Widget instructions.
Zip Widget App
The Zip Widget App is a quick and easy way to install the Zip Widget on your Shopify store. Follow the instructions below to add the widget app and customize it for your store.
First, please check you are using one of the compatible Shopify Themes here.
How to Install the Zip Widget App
1. Navigate to the widget app in Shopify's app store
- Click 'Add app.'
- Click 'Install App.'
- Select your region, enter in your Merchant Id, and click 'Save settings.'
Note: Make sure to select the correct region that matches your Shopify store currency.
- Once you have selected your region, click 'Integrate Widget.'
- Then click 'Customize widget.'
- Now, select where you would like the widget to appear in the 'Widget' tab.
- Once you have selected your preferred Zip widget settings, click 'Save.'
Congratulations — well done!
View the theme you just worked on. If the widget was integrated properly, it should appear in your product page, mini cart, and cart. If it doesn't, you will need to integrate via Classic Widget instructions.
If you have any questions or are encountering any difficulties, please contact us at [email protected].
Integrate with the Classic Widget
Before You Start
These instructions are for a Shopify store using one of the default Shopify or lightly customized themes. If the store's theme is heavily customized, you may have to add the below snippets to different templates and files.
For additional integration support: email us
Add Widget to PDP
- Login to your Shopify store.
- In the left menu, click Online Store
- For the theme you would like to edit, expand the Actions menu and choose Edit Code.
We recommend adding the Zip widget to a development theme or a copy of the currently live theme. This way you can control when you share the integration with your customers.
- In the Layout menu to the left, open theme.liquid.

- In the theme.liquid file, before the closing
</body>
tag, insert this script which calls the Zip informational modal from each widget:
<!-- quadpay.js Library -->
<script src="https://cdn.us.zip.co/v1/quadpay.js"></script>
Then Click Save.
- Locate the Product Details Page template. Often this is in the Sections folder in the file product-template.liquid file. (If your theme is customized, the Product Details Page template may be in another file.) Inside the Product Details Page template, locate where the price is displayed. Then, right below the Product Price, paste in this snippet. Click Save.
<!-- Insert Zip Widget -->
<quadpay-widget-v3 amount={{ current_variant.price | divided_by: 100.00 }}></quadpay-widget-v3>
- Note the variable that is used to display the price. Paste this same price variable after
amount=
in the above snippet. Shopify uses a variety of variables to indicate the product price, including:
Current_variant.price
Variant.price
Product.price
Product.selected_or_first_available_variant.price
- If the price is displayed with a JavaScript variable, you may need to wrap the price variable in raw tags as follows:
{% raw %} {{{totalQPPrice}}} {% endraw %}
Note: If the above snippet always shows "4 interest-free payments on orders over ${min price}
even when the price is above the minimum allowed price, the price variable after amount=
needs to be replaced.
- Click the Preview link in the top menu to preview the Zip Widget in this theme.

Customizing the Styling of the Zip Widget
For guidance on customizing the styling of the widget, visit the Zip Widget Integration Guide.
Add Widget to Cart
After you have added the widget to the Product Details Page template, add the widget to the Cart template.
- Locate the Cart template. Often this is in the Sections folder in the file cart-template.liquid file. (If your theme is customized, the Cart template may be in another file.) Inside the Cart template, locate where the price is displayed. Then, right below the Cart Subtotal or Cart Total, paste in this snippet. Click Save.
<!-- Insert Zip Widget -->
<quadpay-widget-v3 amount={{ cart.total_price | divided_by: 100.00 }} merchantId="[Insert merchant Id]" ></quadpay-widget-v3>
-
Note the variable that is used to display the cart total. Paste this same cart total variable after
amount=
in the above snippet. Shopify uses various variables to indicate the cart total, but typically the cart total variable is:cart.total_price
Note: If the above snippet always shows "4 interest-free payments on orders over${min price}
even when the price is above the minimum allowed price, the cart total variable afteramount=
needs to be updated. -
Click the Preview link in the top menu to preview the Zip Widget in this theme.

Customizing the Styling of the Zip Widget
For guidance on customizing the styling of the widget, visit the Zip Widget Integration Guide.
Add Widget to Mini Cart
If your site uses a Mini Cart, after you add the widget to the Product Details Page and Cart templates, add the widget to the Mini Cart.
- Locate the Mini Cart template. Often this is handled in the Layout/theme.liquid file, but the mini cart is also frequently handled through separate JavaScript files in the Assets folder. Inside the Mini Cart file, locate where the price is displayed. Then, right below the Cart Subtotal or Cart Total, paste in this snippet. Click Save.
<!-- Insert Zip Widget -->
<quadpay-widget-v3 amount={{ cart.total_price | divided_by: 100.00 }} merchantId="[Insert merchant Id]" ></quadpay-widget-v3>
-
Note the variable that is used to display the mini cart total. Paste this same variable after
amount=
in the above snippet. Shopify uses various variables to indicate the cart total in the mini cart, but often the mini cart total variable is:cart.total_price
or{{{totalPrice}}}
Note: If the above snippet always shows "4 interest-free payments on orders over${min price}
even when the price is above the minimum allowed price, the cart total variable afteramount=
needs to be updated. -
Click the Preview link in the top menu to preview the Zip Widget in this theme.

Sometimes, the Mini Cart is already quite customized and integrating the Zip widget requires additional customizing. If you would like support with adding the widget to the Mini Cart or for any questions please get in touch with us.
Manually Uninstalling the Shopify Widget
If you're upgrading from our legacy Shopify Messaging app to our new Shopify Messaging app, you'll need to manually uninstall the old app.
- Navigate to Sales Channels > Online Store > Themes
- Click the ••• icon to the left of the theme Customize button. Then select 'Edit code'
[block:image]
{
"images": [
{
"image": [
"https://files.readme.io/49f471d-Screenshot_2023-08-25_at_9.33.37_AM.png",
"",
""
],
"align": "center"
}
]
}
[/block] - In the code editor, search for 'zip' (lowercase) and locate the zip-widget.liquid file under the Snippets folder.
[block:image]
{
"images": [
{
"image": [
"https://files.readme.io/4076eae-Screenshot_2023-08-25_at_9.43.06_AM.png",
"",
""
],
"align": "center"
}
]
}
[/block] - Select the trash can icon next to the zip-widget.liquid file and confirm the file deletion.
[block:image]
{
"images": [
{
"image": [
"https://files.readme.io/f2e4104-Screenshot_2023-08-25_at_9.43.14_AM.png",
"",
""
],
"align": "center"
}
]
}
[/block] - The deletion is now complete. You can now either uninstall the Zip On-site Messaging app if you no longer wish to display the Zip placements or you can return to the app Dashboard to start the installation process of the new app.
Issuing Refunds
Issuing refunds for Zip orders is straightforward with the following instructions.
- Locate the Zip order you would like to issue a refund for.
- Click Refund on the Order Details Page.
- Enter the Refund Amount and Reason.
- Click the Refund button. Zip will automatically credit the customer's existing and/or future installments as needed.
- Verify the order status both in both Shopify and also in the Zip Merchant Portal (staging environment).
If the online store doesn't handle issuing refunds directly, the Zip Merchant Portal can be configured to issue refunds. Contact [email protected] to learn more.
Integration guide for Zip MFPP on Shopify Plus
All of the files required for integration are stored in the integration
subdirectory of this repository.
Checkout integration:
Perform the following steps for integration:
-
Open your store's admin area, navigate to Online Store -> Themes. Click on the Actions drop down next to the theme you'd like to integrate Zip MFPP with and select "Edit code".
-
On the left hand side list, under the "Snippets" section, click "Add a new snippet" and name it
zip-checkout-mfpp
. -
Paste the contents of the zip-checkout-mfpp.liquid file into the code area and click "Save" once you finish.
-
On the left hand side, navigate to the "Layout" section and determine if you have a template file called
checkout.liquid
. If you do, you should skip the next step. -
Click on "Add a new layout" and on the dropdown select "checkout", leave the "called" field empty.
-
Paste the following snippet that calls the MFPP script before the
</body>
tag:{% comment %}<!-- Begin Zip checkout MFPP -->{% endcomment %} {% assign zip_merchant_id = 'your-merchant-id' -%} {% include 'zip-checkout-mfpp' %} {% comment %}<!-- End Zip checkout MFPP -->{% endcomment %}
-
Change the
your_merchant_id
value with your Merchant ID. -
Save the file and test the results.
Manually setting the zip_selector
If after step 8, the Merchant Fee for Payment Plan line item does not show at checkout when Zip is selected, you can insert the following line of code to the above snippet in step 6:
{% assign zip_selector = '#checkout_payment_gateway_123456' -%}
Then, navigate to your online store and start the checkout process, navigate to the payment methods step, open the developer console, and find the radio button for Zip. Copy the ID of the radio button and set the
zip_selector
value incheckout.liqud
, in the snippet in step 6, to that ID (instead of 123456). Make sure to prepend the ID with #checkoutpayment_gateway".
That finishes the integration for the payment step and order confirmation pages.

Successful checkout integration
Order confirmation email integration:
Perform the following steps in order to integrate the notification on the confirmation email:
-
Navigate to Settings -> Notifications -> Order confirmation.
-
In the code editor, add the following snippet to the top of the code:
{% comment %} Zip MFPP integration snippet {% endcomment %} {% assign zip_fee = attributes.zip-mfpp-amount | default: 0 | plus: 0 -%} {% comment %} END Zip MFPP integration snippet {% endcomment %}
-
Locate the following line:
<table class="row subtotal-table subtotal-table--total">
-
Above that line, there should be a
</table>
tag. Paste the following snippet of code above it:{% comment %} Zip MFPP integration snippet {% endcomment %} {% if zip_fee > 0 %} <tr class="subtotal-line"> <td class="subtotal-line__title"> <p> <span>Merchant fee for payment plan</span> </p> </td> <td class="subtotal-line__value"> <strong>{{ zip_fee | money }}</strong> </td> </tr> {% endif %} {% comment %} END Zip MFPP integration snippet {% endcomment %}
-
Find the line that contains the following snippet:
<strong>{{ total_price | money_with_currency }}</strong>
Replace that entire line with the contents of the following snippet:
{% comment %} Zip MFPP integration snippet {% endcomment %} <strong>{{ total_price | plus: zip_fee | money_with_currency }}</strong> {% comment %} END Zip MFPP integration snippet {% endcomment %}
-
Locate all instances of
{{ transaction.amount | money }}
and modify them so that you add thezip_fee
value to them by using Liquid'splus
filter. It should look similar to{{ transaction.amount | plus: zip_fee | money }}
.
NOTE
You should only perform step number 6 if you installed Zip payment gateway through the Payments app, if you are using the legacy implementation, you must not perform that step.

Successful email integration.
Shopify Checkout MFPP code
zip-checkout-mfpp.liquid
{% comment %}<!-- Zip MFPP -->{% endcomment %}
{% assign zip_mfpp_url = "https://gateway.quadpay.com/orders/calculate-merchant-fees" -%}
{% if zip_test -%}
{% assign zip_mfpp_url = "https://sandbox.gateway.quadpay.com/orders/calculate-merchant-fees" -%}
{% endif -%}
<script type="application/javascript">
// Zip Checkout MFPP - v1.2.0
{% assign zip_default_money_format = '${{amount}}' -%}
window.QuadPayCheckoutOptions = {
merchantId: "{{zip_merchant_id}}",
state: "{{checkout.shipping_address.province_code | default: checkout.billing_address.province_code}}",
country: "{{checkout.shipping_address.country_code | default: checkout.billing_address.country_code}}",
currency: "{{shop.currency}}",
moneyFormat: "{{zip_money_format | default: zip_default_money_format}}",
quadpayFeeApi: "{{ zip_mfpp_url }}",
quadpayRegion: "{{ zip_region | default: "US" }}"
};
{% if zip_selector %}
window.QuadPayCheckoutOptions.quadpayGatewaySelector = "{{zip_selector}}";
{% endif %}
{% if order.attributes.zip-mfpp-amount -%}
{% comment %}/* Thank You page and paid with Zip. */{% endcomment %}
window.QuadPayCheckoutOptions.thankYouPageFee = {{ order.attributes.zip-mfpp-amount }};
{% endif -%}
/* global document, window */
window.QuadPayCheckout = {
selectors: {
orderSummaryTotalLines: '.total-line-table__tbody',
paymentMethodSection: '.section--payment-method .section__content',
total: '.total-line-table__footer .total-line__price .payment-due__price',
totalRecap: '.total-recap__final-price',
mainForm: "form[data-payment-form]",
paymentMethodTransactions: ".payment-method-list__item__amount",
orderAttributesInputName: "checkout[attributes][zip-mfpp-amount]",
},
quadpayFeeTotalLineClass: '.total-line--quadpay-fee',
init: function(options, step) {
this.options = options;
if (step === 'payment_method') {
this.initPaymentMethodStep();
} else {
this.initThankYouPage();
}
},
initPaymentMethodStep: function() {
const quadpayGatewaySelector = this.options.quadpayGatewaySelector || this.findGatewaySelector();
if (!quadpayGatewaySelector) {
const style = "background-color:white;font-weight:bold;";
console.log(
"%c[ZIP] Cannot find Zip gateway selector, please refer to documentation at: %chttps://docs.us.zip.co/docs/mfpp-shopify-plus",
"color:#411361;" + style,
"color:#6542be;" + style
);
return;
}
this.shopifyTotal = this.getShopifyTotal();
this.monitorGatewaySelection(quadpayGatewaySelector);
this.monitorCurrencySelection();
this.refresh(true);
},
initThankYouPage: function() {
let fee = this.options.thankYouPageFee;
if (fee) {
this.shopifyTotal = this.getShopifyTotal();
this.setTotalLinePriceIncrease(fee, this.options.currency);
this.setQuadPayLinePrice(fee);
}
},
findGatewaySelector: function() {
const identifyingElement = document.querySelector('[data-payment-icon="zip"]') ||
Array.prototype.find.call(document.querySelectorAll('.radio__label__primary'), function (el) {
return el.innerText.match(/(Zip|Quadpay|QuadPay)/);
});
if (!identifyingElement) {
return null;
}
const wrapperElement = this.findClosestParentElement(identifyingElement, ".radio-wrapper");
if (!wrapperElement || !wrapperElement.dataset.selectGateway) {
return null;
}
return "#checkout_payment_gateway_" + wrapperElement.dataset.selectGateway;
},
findClosestParentElement: function(element, selector) {
if (element.closest && typeof element.closest === "function") {
return element.closest(selector);
}
const findClosest = function (element, selector) {
if (element.matches(selector)) {
return element;
} else if (!element.parentNode) {
return null;
}
return findClosest(element.parentNode, selector);
};
return findClosest(element, selector);
},
refresh: function(reloadFee) {
if (reloadFee === true) {
this.fee = null;
}
this.getQuadPayFee().then((function (fee) {
this.fee = fee;
if (this.quadpayIsSelected === true) {
this.repaintFee(this.fee);
this.generateOrderAttributesInput(this.fee);
} else {
this.hideFee();
this.removeOrderAttributesInput();
}
}).bind(this));
},
repaintFee: function(fee) {
this.setTotalLinePriceIncrease(fee);
this.setQuadPayLinePrice(fee);
},
hideFee: function() {
this.setTotalLinePriceIncrease(0);
this.setQuadPayLinePrice(null);
},
setTotalLinePriceIncrease: function(fee, currency) {
const money = this.formatInCurrency(this.shopifyTotal + fee, currency);
const selector = this.selectors.total + ',' + this.selectors.totalRecap + ',' + this.selectors.paymentMethodTransactions;
document.querySelectorAll(selector).forEach(function(el) {
el.innerHTML = money;
});
},
setQuadPayLinePrice: function(fee) {
let quadPayLine = document.querySelector(this.quadpayFeeTotalLineClass);
if (quadPayLine) {
quadPayLine.parentNode.removeChild(quadPayLine);
}
if (fee === null || fee < 0.01) {
return;
}
this.generateQuadPayFeeLine(fee);
},
monitorGatewaySelection: function(quadpayGatewaySelector) {
this.quadpayIsSelected = null;
const gatewaySelected = (function() {
const radio = document.querySelector(quadpayGatewaySelector);
const isSelected = radio && radio.checked;
const shouldRefresh = this.quadpayIsSelected !== null && this.quadpayIsSelected !== isSelected;
this.quadpayIsSelected = isSelected;
if (shouldRefresh) {
this.refresh(false);
}
}).bind(this);
const paymentMethodSection = document.querySelector(this.selectors.paymentMethodSection);
if (!paymentMethodSection) {
return;
}
paymentMethodSection.addEventListener('click', gatewaySelected);
gatewaySelected();
},
monitorCurrencySelection: function() {
const currencies = document.querySelector("#currencies");
if (!currencies) {
return;
}
currencies.addEventListener('change', (function () {
this.refresh(false);
}).bind(this));
},
generateQuadPayFeeLine: function(fee) {
let subtotalsElement = document.querySelector(this.selectors.orderSummaryTotalLines);
if (subtotalsElement) {
subtotalsElement.insertAdjacentHTML('beforeend', this.generateLine(fee));
}
},
removeOrderAttributesInput: function() {
document.getElementsByName(this.selectors.orderAttributesInputName).forEach(function (input) {
try {
input.parentNode.removeChild(input);
} catch (_) {}
});
},
generateOrderAttributesInput: function(fee) {
const orderAttributeInputs = document.getElementsByName(this.selectors.orderAttributesInputName);
let orderAttributeInput = orderAttributeInputs.length > 0 ? orderAttributeInputs[0] : null;
if (!orderAttributeInput) {
const form = document.querySelector(this.selectors.mainForm);
if (!form) {
return;
}
orderAttributeInput = document.createElement("input");
orderAttributeInput.setAttribute("type", "hidden");
orderAttributeInput.setAttribute("name", this.selectors.orderAttributesInputName);
form.appendChild(orderAttributeInput);
}
orderAttributeInput.setAttribute("value", fee);
},
generateLine: function(fee) {
const money = this.formatInCurrency(fee);
let className = this.quadpayFeeTotalLineClass.replace(/^\./, '');
return '<tr class="total-line ' + className + '">' +
'<th class="total-line__name" scope="row">Merchant Fee for Payment Plan</th>' +
'<td class="total-line__price"><b>' + money + '</b></td>' +
'</tr>';
},
getQuadPayFee: function() {
if (this.fee !== null) {
return Promise.resolve(this.fee);
}
return this.fetchFee().then(function(data) {
if (!('merchantFeeForPaymentPlan' in data)) {
return Promise.resolve(null);
}
let fee = parseFloat(data.merchantFeeForPaymentPlan) * 100;
return Promise.resolve(fee);
});
},
fetchFee: function() {
let totalForQuadPay = this.shopifyTotal / 100;
let dataForQuadPay = {
merchantId: this.options.merchantId,
currency: this.options.currency,
customerCountry: this.options.country,
amount: totalForQuadPay
};
if (this.options.state) {
dataForQuadPay.customerState = this.options.state;
}
return window.fetch(this.options.quadpayFeeApi, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'QP-Territory': this.options.quadpayRegion
},
body: JSON.stringify(dataForQuadPay)
}).then(function (response) {
return response.json();
});
},
getShopifyTotal: function() {
let totalElement = document.querySelector(this.selectors.total);
if (!totalElement) {
return;
}
return parseInt(totalElement.getAttribute('data-checkout-payment-due-target'), 10);
},
formatInCurrency: function (amount, currency) {
if (window.Currency) {
const currentCurrency = currency || window.Currency.cookie.read();
const total = window.Currency.convert(amount, window.Shopify.Checkout.currency || this.options.currency, currentCurrency);
const moneyFormat = window.Currency.moneyFormats[currentCurrency][window.Currency.format];
return window.Currency.formatMoney(total, moneyFormat);
}
return this.shopifyFormatMoney(amount);
},
shopifyFormatMoney: function(cents) {
if (typeof cents == 'string') {
cents = cents.replace('.','');
}
let value = '';
let placeholderRegex = /\{\{\s*(\w+)\s*\}\}/;
let formatString = this.options.moneyFormat;
function defaultOption(opt, def) {
return (typeof opt == 'undefined' ? def : opt);
}
function formatWithDelimiters(number, precision, thousands, decimal) {
precision = defaultOption(precision, 2);
thousands = defaultOption(thousands, ',');
decimal = defaultOption(decimal, '.');
if (isNaN(number) || number == null) { return 0; }
number = (number/100.0).toFixed(precision);
let parts = number.split('.'),
dollars = parts[0].replace(/(\d)(?=(\d\d\d)+(?!\d))/g, '$1' + thousands),
cents = parts[1] ? (decimal + parts[1]) : '';
return dollars + cents;
}
switch(formatString.match(placeholderRegex)[1]) {
case 'amount':
value = formatWithDelimiters(cents, 2);
break;
case 'amount_no_decimals':
value = formatWithDelimiters(cents, 0);
break;
case 'amount_with_comma_separator':
value = formatWithDelimiters(cents, 2, '.', ',');
break;
case 'amount_no_decimals_with_comma_separator':
value = formatWithDelimiters(cents, 0, '.', ',');
break;
}
return formatString.replace(placeholderRegex, value);
}
};
(function() {
let step = window.Shopify.Checkout.step;
if (!step && window.QuadPayCheckoutOptions.thankYouPageFee) {
step = 'thank_you';
}
if (['payment_method', 'thank_you'].indexOf(step) !== -1) {
window.QuadPayCheckout.init(window.QuadPayCheckoutOptions, step);
}
// re-init on apply gift card and calculating taxes
if (step === 'payment_method') {
document.addEventListener('page:change', function () {
window.setTimeout(function () {
window.QuadPayCheckout.init(window.QuadPayCheckoutOptions, step);
}, 500);
});
}
})();
</script>
Matching Zip and Shopify Orders
When an order is placed through Shopify, there is an Id called the Payment Id set on the order. You can find this Id in Shopify, in the order Timeline section. Navigate to the Timeline event that says "A $X USD payment was authorized on Zip (US)," then expand the "Information from the gateway" section to reveal the Payment Id.
You will find this Payment Id in your Zip Merchant Portal in the Merchant Reference field.
Note
Shopify does not provide Zip with the Shopify Order Id. You will need the Shopify Payment Id in order to associate Shopify and Zip orders.
Find Orders in Shopify with a Zip Order Number
-
To find the corresponding Shopify order from a Zip order, find the Payment Id in the Merchant Reference field in the Zip Merchant Portal or via the Zip Reporting API.
-
From your Shopify admin, go to Orders.
-
Search using the custom term receipt.payment_id: and the Payment Id value.
For example: receipt.payment_id:xxx.
-
Click on the order.
-
To verify the gateway and payment information, click on the specific event in the Shopify order Timeline. For more information, refer to View payment events from the Timeline.
Reconcile Zip and Shopify Orders
When you need to reconcile a large number of orders between Zip and Shopify, you can use the Payment Id to do so.
-
From your Shopify admin, go to Orders.
-
Click Export, choose the order range to export and click Export orders
-
In the Zip Merchant Portal or Reporting API, download the selection of transactions to reconcile.
-
Match the Payment Id from the Shopify order export to the Merchant Reference value in the Zip export.
Updated 29 days ago