Overview
This guide walks you through integrating your Shopify store with SubscriptionFlow.
Step 1: Create Your SubscriptionFlow Shopify App
Follow this official SubscriptionFlow guide:
https://support.subscriptionflow.com/hc/en-us/articles/28207837443353-Create-SF-App-inside-Shopify
Step 2: Configure the App with SubscriptionFlow
Once the app is created, sync it with your SubscriptionFlow account by following:
https://support.subscriptionflow.com/hc/en-us/articles/34486014267929-Shopify-Integration-Guide
Step 3: Set Up Product Variants
To make SubscriptionFlow work with product pages, create variants representing purchase frequencies.
Steps:
1. Go to Products > Select a Product
2. Under Variants > Options, configure:
- Option Name: Purchase options
- Option Values:
- One-Time Purchase
- Every Week
- Every 2 Weeks
- Every 3 Weeks
- Every 4 Weeks
- ...and so on
Each frequency must be its own variant for the integration to work.
Step 4: Product Page Integration (For handling Subscription & One-Time Buy)
1. Create a Product Template
- Go to: Online Store > Themes > Customize
- Open any Product Page
- Click the top dropdown → Create template
- Name it something like subscription-product
- Save it
2. Add Subscription Logic
- Click Add block > Custom Liquid
- Paste the subscription logic (JS + Liquid) into the block
- Include radio buttons, hidden variant ID logic, and SF URL logic
3. Assign Template to Product
- In Shopify Admin, open the product
- Scroll to Theme Template and assign the new template
- Save
Sample Code To Add in Custom Liquid
HTML Code:
<label for="subscribe-select" class="styled-label form__label">Purchase Option: <span id="label-text"> Once-off</span></label>
<div class="purchase-tabs">
<button type="button" class="tab-btn active" data-type="one-off"> Once-off</button>
<button type="button" class="tab-btn" data-type="subscribe">Subscribe<span class="menu-item-badge" style="--menu-badge-bg: #eff0f2;--menu-badge-text: #272422;">SAVE 10%</span></button>
</div>
<!-- Hidden input to store selected variant ID -->
<input type="hidden" name="id" id="variant-id" value="{{ product.variants.first.id }}">
<div class="subscribe-options" style="display: none;">
<svg width="8" height="6" viewBox="0 0 8 6" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M6.75 1.5L3.75 4.5L0.75 1.5" stroke="var(--color-header-links, --color-accent)" stroke-width="1.1" stroke-linecap="round" stroke-linejoin="round"></path>
</svg>
<select id="subscribe-select" name="Fequency" class="styled-select">
<option value="1 Week" data-variant-id="50322934661413">Weekly</option>
<option value="2 Week" data-variant-id="50359818354981">Every 2 Weeks</option>
<option value="4 Weeks" data-variant-id="50359818387749">Monthly</option>
<option value="6 Weeks" data-variant-id="50359818420517">Every 6 Weeks</option>
</select>
</div>
JavaScript Code :
<script>
document.addEventListener("DOMContentLoaded", async () => {
const shopifyVariants = [
{% for variant in product.variants %}
{
id: "{{ variant.id }}",
title: "{{ variant.title | escape }}"
}{% unless forloop.last %},{% endunless %}
{% endfor %}
];
const productId = "{{ product.id }}";
try {
//const frequencyLabels = ["1 Week", "2 Week","1 Month" , "6 Week","3 Month","6 Month","12 Month"];
const frequencyLabels = ["1 Week", "2 Week","1 Month" , "6 Week"];
const sf_variant_mapped_shopify = {};
// Build basic mapping for demonstration
shopifyVariants.forEach(variant => {
const variantId = variant.id;
sf_variant_mapped_shopify[variantId] = {};
frequencyLabels.forEach(label => {
const sanitized = label.toLowerCase().replace(/\s+/g, '_');
const value = (label === "1 Week")
? variantId
: `${sanitized}_${variantId}`;
sf_variant_mapped_shopify[variantId][label] = value;
});
});
console.log("Mapped Plans aaa:", sf_variant_mapped_shopify);
// DOM elements
const subscribeSelect = document.getElementById("subscribe-select");
const hiddenSubscriptionFrequency = document.getElementById("hidden-subscription-frequency");
const hiddenSubscriptionFrequencyLabel = document.getElementById("hidden-subscription-frequency-label");
const ShowlabelText = document.getElementById("label-text");
const tabButtons = document.querySelectorAll(".tab-btn");
const subscribeOptions = document.querySelector(".subscribe-options");
// Function to update select dropdown
function updateSubscribeSelect(variantId) {
const frequencyOptions = sf_variant_mapped_shopify[variantId];
if (frequencyOptions && subscribeSelect) {
subscribeSelect.innerHTML = "";
for (const [label, value] of Object.entries(frequencyOptions)) {
let displayLabel = label;
// Custom label mapping
switch (label.toLowerCase()) {
case "1 week":
displayLabel = "Weekly";
break;
case "2 week":
displayLabel = "Every 2 Weeks";
break;
case "1 month":
displayLabel = "Monthly";
break;
case "6 week":
displayLabel = "Every 6 Weeks";
break;
case "3 month":
displayLabel = "Every 3 Months";
break;
case "6 month":
displayLabel = "Every 6 Months";
break;A
case "12 month":
displayLabel = "Every 12 Months";
break;
}
const option = document.createElement("option");
option.value = value;
option.textContent = displayLabel;
subscribeSelect.appendChild(option);
}
updateHiddenFields();
}
}
// Hidden input updater
function updateHiddenFields() {
const activeTab = document.querySelector(".tab-btn.active");
if (subscribeSelect && activeTab && activeTab.getAttribute("data-type") === "subscribe") {
hiddenSubscriptionFrequency.value = subscribeSelect.value || "";
hiddenSubscriptionFrequencyLabel.value = subscribeSelect.options[subscribeSelect.selectedIndex]?.text || "";
ShowlabelText.innerHTML = subscribeSelect.options[subscribeSelect.selectedIndex]?.text || "";
} else {
hiddenSubscriptionFrequency.value = "";
hiddenSubscriptionFrequencyLabel.value = "";
ShowlabelText.innerHTML = "Once-off";
}
}
// Set initial state
updateSubscribeSelect("{{ product.selected_or_first_available_variant.id }}");
// Tab switching
tabButtons.forEach((btn) => {
btn.addEventListener("click", function () {
tabButtons.forEach(b => b.classList.remove("active"));
this.classList.add("active");
if (this.getAttribute("data-type") === "subscribe") {
subscribeOptions.style.display = "block";
updateHiddenFields();
} else {
subscribeOptions.style.display = "none";
hiddenSubscriptionFrequency.value = '';
hiddenSubscriptionFrequencyLabel.value = '';
ShowlabelText.innerHTML = "Once-off";
}
});
});
// Variant change from URL
window.addEventListener("change", function (e) {
if (e.target.id === "subscribe-select") return;
const urlParams = new URLSearchParams(window.location.search);
const variantId = urlParams.get('variant');
if (variantId) {
updateSubscribeSelect(variantId);
}
});
// Select change
if (subscribeSelect) {
subscribeSelect.addEventListener("change", function () {
updateHiddenFields();
console.log("Selected subscription variant ID:", subscribeSelect.value);
});
}
} catch (err) {
console.error("Error fetching or processing plans:", err);
}
});
</script>
Step 5: Cart Page Integration (Handling Subscription & One-Time Buy)
To handle checkout redirection based on cart contents (subscription vs one-time items), update your cart.liquid or cart section file.
https://support.subscriptionflow.com/hc/en-us/articles/31279396193817-Embed-Checkout-into-Cart
Objective
If the cart contains only one-time purchase items → Redirect to Shopify checkout
If the cart contains any subscription item → Redirect to SubscriptionFlow checkout
Add the following code to your cart template
a) Checkout Button (Liquid)
<a
{% if cart == empty %}disabled{% endif %}
id="sf-checkout-link"
href="#"
class="cart__checkout-button button"
style="width: 100%;"
>
<span class="button__label">{{ 'sections.cart.checkout' | t }}</span>
</a>
b) JavaScript Logic
<script>
function fetchCartDetails() {
return fetch('/cart.js')
.then(response => response.json())
.catch(error => {
console.error('❌ Error fetching cart details:', error);
});
}
function sf_checkout_button() {
fetchCartDetails().then(cart => {
let allOneTime = true;
let sfUrl = 'https://yourstore.subscriptionflow.com/en/hosted-page/commerceflow?';
if (cart && cart.items && cart.items.length > 0) {
cart.items.forEach((item, index) => {
const isSubscription = !item.title.includes("One-Time Purchase"); // Adjust if needed
if (isSubscription) {
allOneTime = false;
}
sfUrl += `items[${index}][pr]=${item.product_id}&items[${index}][pl]=${item.variant_id}&items[${index}][q]=${item.quantity}&`;
});
}
if (allOneTime) {
console.log("🛍️ All one-time items — redirecting to Shopify checkout");
window.location.href = "/checkout";
} else {
sfUrl += 'cart=https://yourstore.com/';
console.log("🔁 Contains subscription — redirecting to SubscriptionFlow");
window.location.href = sfUrl;
}
});
}
document.addEventListener("DOMContentLoaded", function () {
const checkoutBtn = document.getElementById("sf-checkout-link");
if (!checkoutBtn) {
console.warn("❌ #sf-checkout-link not found.");
return;
}
checkoutBtn.addEventListener("click", function (event) {
event.preventDefault();
sf_checkout_button();
});
});
</script>
Step 6: Embed Customer Portal
Follow the guide below to embed the SubscriptionFlow in-app customer portal:
https://support.subscriptionflow.com/hc/en-us/articles/28207837443353-Create-SF-App-inside-Shopify
Comments
0 comments
Article is closed for comments.