Before you begin: If you have not completed the following
three setup steps yet, go through them first:
If you want to use the SubscriptionFlow checkout on Wix, follow these steps. On the cart page you simply need to add the custom element below, and set the cart page code to the value shown here. With these two steps, subscription orders will be redirected to the SubscriptionFlow checkout directly from the cart page.
Contents
Important: In the code below, replace
https://your-site.subscriptionflow.com with your own
SubscriptionFlow tenant name (for example,
https://yourcompany.subscriptionflow.com).
1. Custom Element — Cart Page
subscriptionflow-button-add.js
Controls checkout behavior on cart page.
// Debug toggle
const DEBUG_SF = true;
function dlog(label, color, ...args) {
if (!DEBUG_SF) return;
console.log(
`%csf-your-site: ${label}`,
`color:${color};font-weight:600;`,
...args,
);
}
function dgroup(label, color) {
if (!DEBUG_SF) return { end: () = {} };
console.groupCollapsed(
`%csf-your-site: ${label}`,
`color:${color};font-weight:700;`,
);
return { end: () = console.groupEnd() };
}
class SubscriptionflowButtonAdd extends HTMLElement {
static get observedAttributes() {
return ["customdatacart", "customerdatjsons"];
}
constructor() {
super();
this.attachShadow({ mode: "open" });
this.cart = null;
this.intervalId = null;
this.customerData = null;
this.activeCoupon = null;
dlog("Constructor initialized", "purple");
}
connectedCallback() {
dlog("Connected to DOM", "green");
this.startButtonPolling();
this.updateButtonLogic();
}
disconnectedCallback() {
dlog("Disconnected from DOM", "red");
if (this.intervalId) {
clearInterval(this.intervalId);
}
}
attributeChangedCallback(name, oldValue, newValue) {
dlog(`Attribute changed → ${name}`, "orange", { oldValue, newValue });
if (name === "customdatacart" && newValue !== oldValue) {
try {
this.cart = JSON.parse(newValue);
dlog("Cart parsed successfully", "green", this.cart);
// ✅ ADD THIS
this.activeCoupon = this.resolveCouponFromWix(this.cart);
dlog("Resolved coupon", "teal", this.activeCoupon);
this.updateButtonLogic();
} catch (err) {
console.error("sf-your-site: Cart parse error:", err);
}
}
if (name === "customerdatjsons" && newValue !== oldValue) {
try {
this.customerData = JSON.parse(newValue);
dlog("Customer data parsed", "green", this.customerData);
} catch (err) {
this.customerData = newValue;
dlog("Customer data raw fallback", "yellow", this.customerData);
}
}
}
getNonManagedVariantId(productId) {
dlog("Generating fallback variant ID", "blue", productId);
if (typeof productId !== "string" || productId.length !== 36) {
dlog("Invalid productId for variant", "red", productId);
return null;
}
return productId.substring(0, 14) + "vn01" + productId.substring(18);
}
startButtonPolling() {
dlog("Starting checkout button polling", "blue");
this.intervalId = setInterval(() = {
const checkoutBtn = document.querySelector(
'[data-wix-checkout-button="CheckoutButtonDataHook.button"]',
);
if (checkoutBtn) {
dlog("Checkout button found", "green", checkoutBtn);
clearInterval(this.intervalId);
this.intervalId = null;
this.updateButtonLogic();
} else {
dlog("Waiting for checkout button...", "gray");
}
}, 500);
}
addOrReplaceParams(url, params) {
try {
const u = new URL(url);
Object.entries(params).forEach(([k, v]) = {
if (v === undefined || v === null || v === "") return;
u.searchParams.set(k, String(v));
});
return u.toString();
} catch (e) {
return url;
}
}
resolveCouponFromWix(cartData) {
try {
const d1 = cartData?.appliedDiscounts?.find?.((d) = d?.coupon?.code)
?.coupon?.code;
if (d1) return String(d1);
const d2 =
cartData?.discounts?.appliedCoupons?.[0]?.code ||
cartData?.discounts?.appliedCoupons?.[0]?.couponCode;
if (d2) return String(d2);
const d3 =
cartData?.totals?.coupon?.code || cartData?.totals?.coupon?.couponCode;
if (d3) return String(d3);
return null;
} catch (e) {
console.warn("sf-your-site: coupon resolve failed", e);
return null;
}
}
updateButtonLogic() {
const grp = dgroup("updateButtonLogic()", "purple");
try {
const checkoutBtn = document.querySelector(
'[data-wix-checkout-button="CheckoutButtonDataHook.button"]',
);
if (!checkoutBtn) {
dlog("Checkout button NOT found", "red");
grp.end();
return;
}
if (!this.cart) {
dlog("Cart not available yet", "orange");
grp.end();
return;
}
const lineItems = this.cart.lineItems || [];
dlog("Cart line items", "blue", lineItems);
const existing = document.querySelector("#subscribe-now-link");
const targetItems = lineItems;
dlog("Filtered target items", "blue", targetItems);
if (!targetItems.length) {
dlog("No target product → normal checkout", "green");
checkoutBtn.style.display = "";
if (existing) existing.remove();
grp.end();
return;
}
const purchaseOptions = targetItems.map(
(item) =
item?.catalogReference?.options?.options?.["Purchase Option"] || "",
);
dlog("Purchase options", "blue", purchaseOptions);
const allOneTime = purchaseOptions.every(
(option) = !option || option === "One-Time",
);
if (allOneTime) {
dlog("All items One-Time → normal checkout", "green");
checkoutBtn.style.display = "";
if (existing) existing.remove();
grp.end();
return;
}
dlog("Subscription detected → switching to SF checkout", "purple");
checkoutBtn.style.display = "none";
let url_param_list = "";
let counter = 0;
targetItems.forEach((item) = {
const wixProductID = item.catalogReference?.catalogItemId || "";
const wixVariantID = item.catalogReference?.options?.variantId || "";
const quantity = item.quantity;
let sf_product = wixProductID;
let sf_variant =
wixVariantID &&
wixVariantID !== "00000000-0000-0000-0000-000000000000"
? wixVariantID
: this.getNonManagedVariantId(wixProductID);
dlog("Item mapping", "blue", {
sf_product,
sf_variant,
quantity,
});
if (sf_product && sf_variant) {
url_param_list += `items[${counter}][pr]=${encodeURIComponent(sf_product)}&items[${counter}][pl]=${encodeURIComponent(sf_variant)}&items[${counter}][q]=${encodeURIComponent(quantity)}&`;
counter++;
}
});
let customerParams = "";
if (this.customerData) {
dlog("Adding customer data to URL", "blue", this.customerData);
const fullName = this.customerData.name || "";
/*
// ✅ ADD HERE
const shippingType = this.cart?.shippingInfo?.type || "flat";
const shippingAmount = this.cart?.totals?.shipping || 0;
dlog("Shipping Data", "teal", {
shippingType,
shippingAmount,
cartShippingInfo: this.cart?.shippingInfo,
cartTotals: this.cart?.totals
});
*/
const queryParams = new URLSearchParams({
ai_email: this.customerData.email || "",
ai_firstName: "",
ai_lastName: fullName,
ai_phone: this.customerData.phone_number || "",
ai_billing_country: this.customerData.billing_country || "",
ai_shipping_country: this.customerData.shipping_country || "",
});
customerParams = queryParams.toString();
}
// ✅ Get selected shipping code
const selectedShippingCode =
this.cart?.selectedShippingOption?.code || "";
dlog("Selected Shipping Code", "teal", selectedShippingCode);
// ✅ Condition check
let shippingParam = "";
if (selectedShippingCode === "fff0f7bb2cdc4b10a7f9596c59fde242") {
shippingParam = "&shipping_method=Priority+Shipping";
dlog("Priority Shipping Applied", "green");
} else {
dlog("No Shipping Param Applied", "yellow");
}
// ✅ Final URL
// const fullUrl =
// `https://your-site.subscriptionflow.com/en/hosted-page/commerceflow?` +
// `${url_param_list}${customerParams ? "&" + customerParams : ""}` +
// `${shippingParam}` +
// `&cart=${encodeURIComponent("https://www.your-site.com")}`;
// const fullUrl =
// `https://your-site.subscriptionflow.com/en/hosted-page/commerceflow?` +
// `${url_param_list}${customerParams ? "&" + customerParams : ""}` +
// `&cart=${encodeURIComponent("https://www.your-site.com")}`;
let fullUrl =
`https://your-site.subscriptionflow.com/en/hosted-page/commerceflow?` +
`${url_param_list}${customerParams ? "&" + customerParams : ""}` +
`${shippingParam}` +
`&cart=${encodeURIComponent("https://www.your-site.com/cart-page")}`;
// ✅ ADD THIS BLOCK
if (fullUrl && this.activeCoupon) {
fullUrl = this.addOrReplaceParams(fullUrl, {
coupon_code: this.activeCoupon,
});
dlog("Coupon applied to URL", "green", this.activeCoupon);
}
dlog("Final SF URL", "green", fullUrl);
if (existing) {
existing.href = fullUrl;
dlog("Updated existing subscribe link", "green");
} else {
const link = document.createElement("a");
link.id = "subscribe-now-link";
link.textContent = "Checkout";
link.href = fullUrl;
link.target = "_self";
link.style.cssText = `
display: flex;
padding: 10px 20px;
margin-top: 10px;
justify-content: center;
background-color: #1e4383;
color: white;
border-radius: 0px;
font-size: 16px;
text-align: center;
text-decoration: none;
cursor: pointer;
`;
checkoutBtn.parentNode.insertBefore(link, checkoutBtn.nextSibling);
dlog("Created new subscribe button", "green");
}
} catch (e) {
console.error("sf-your-site: updateButtonLogic error:", e);
}
grp.end();
}
}
customElements.define("subscriptionflow-button-add", SubscriptionflowButtonAdd);
Once you add this code to the file, go to the Cart Page in
the Wix Editor and drag a Custom Element onto the page.
Select this file as its source, and set the tag name to
subscriptionflow-button-add.
2. Cart Page Code
Handles cart data and checkout routing.
import wixEcomFrontend from 'wix-ecom-frontend';
import wixEcomBackend from 'wix-ecom-backend';
import { fetchCustomerDetail, myGetCurrentCartFunction } from 'backend/siteApi.web';
import { session } from 'wix-storage';
import wixUsers from 'wix-users';
$w.onReady(async function () {
console.log("sf-your-site: Page Ready Triggered");
if (wixUsers.currentUser.loggedIn) {
console.log("sf-your-site: User is logged in");
const email = await wixUsers.currentUser.getEmail();
console.log("sf-your-site: User email fetched:", email);
if (email && !session.getItem("customerData")) {
console.log("sf-your-site: Fetching customer data...");
const customerData = await fetchCustomerDetail(email);
if (customerData) {
session.setItem("customerData", JSON.stringify(customerData));
console.log("sf-your-site: Customer data saved in session:", customerData);
} else {
console.log("sf-your-site: No customer data found for email:", email);
}
} else {
console.log("sf-your-site: Customer data already exists in session or email missing");
}
} else {
console.log("sf-your-site: User NOT logged in");
}
console.log("sf-your-site: Calling updateCustomElementCart()");
updateCustomElementCart();
wixEcomFrontend.onCartChange(() = {
console.log("sf-your-site: Cart change detected");
updateCustomElementCart();
});
});
async function updateCustomElementCart() {
try {
console.log("sf-your-site: updateCustomElementCart() started");
const cartData = await myGetCurrentCartFunction();
console.log("sf-your-site: Cart data received:", cartData);
const cartItems = cartData?.lineItems || [];
console.log("sf-your-site: Cart items count:", cartItems.length);
if (cartItems.length 0) {
const session_customerData = session.getItem("customerData");
console.log("sf-your-site: Session customer data:", session_customerData);
const cartJson = JSON.stringify(cartData);
console.log("sf-your-site: Setting cart data to custom element");
$w('#customElement1').setAttribute('customdatacart', cartJson);
if (session_customerData) {
console.log("sf-your-site: Setting customer data to custom element");
$w('#customElement1').setAttribute('customerdatjsons', session_customerData);
} else {
console.log("sf-your-site: No customer data found in session");
}
} else {
console.log("sf-your-site: No items in cart");
}
} catch (error) {
console.error("sf-your-site: ERROR in updateCustomElementCart:", error);
}
}
Comments
0 comments
Please sign in to leave a comment.