v0.1

ModalsUX
#91 - Hide Popup For Set Duration
Hide a popup for X time when a button is clicked.
Watch the video for step-by-step implementation instructions
<!-- 💙 MEMBERSCRIPT #222 v0.1 💙 SUBSCRIPTION PLAN RETENTION FLOW -->
<script>
document.addEventListener("DOMContentLoaded", async function() {
var CONFIG = {
webhookUrl: "",
couponId: "",
jsonKey: "retention_offered",
maxOffers: 1,
cooldownDays: 30,
portalReturnUrl: window.location.href,
modalDisplay: "flex"
};
var memberstack = window.$memberstackDom;
if (!memberstack) {
console.warn("Memberscript # number222: Memberstack not found");
return;
}
// ─── GET MEMBER ───
var member;
try {
var memberResult = await memberstack.getCurrentMember();
member = memberResult?.data || memberResult;
} catch (err) {
console.warn("Memberscript # number222: Could not get member", err);
return;
}
if (!member || !member.id) return;
var memberJSON = {};
try {
var jsonResult = await memberstack.getMemberJSON();
memberJSON = jsonResult?.data || {};
} catch (e) {}
// ─── DOM REFERENCES ───
var modal = document.querySelector('[data-ms-retain="modal"]');
var triggers = document.querySelectorAll('[data-ms-retain="cancel-trigger"]');
if (!modal || triggers.length === 0) return;
function hideTriggers() {
triggers.forEach(function(t) { t.style.display = "none"; });
}
var planConnections = member.planConnections || [];
var activeSubs = planConnections.filter(function(pc) {
return pc.status === "ACTIVE" && pc.type === "SUBSCRIPTION";
});
if (activeSubs.length === 0) { hideTriggers(); return; }
var views = {
offer: modal.querySelector('[data-ms-retain="offer"]'),
loading: modal.querySelector('[data-ms-retain="loading"]'),
success: modal.querySelector('[data-ms-retain="success"]'),
error: modal.querySelector('[data-ms-retain="error"]')
};
var acceptBtn = modal.querySelector('[data-ms-retain="accept"]');
var declineBtn = modal.querySelector('[data-ms-retain="decline"]');
var closeBtns = modal.querySelectorAll('[data-ms-retain="close"]');
var retryBtn = modal.querySelector('[data-ms-retain="retry"]');
// ─── READ CONFIG FROM ATTRIBUTES ───
var webhookUrl = modal.getAttribute("ms-retain-webhook") || CONFIG.webhookUrl;
var couponId = modal.getAttribute("ms-retain-coupon") || CONFIG.couponId;
var fieldKey = modal.getAttribute("ms-retain-field") || CONFIG.jsonKey;
var targetPlanId = modal.getAttribute("ms-retain-plan") || "";
var maxOffers = parseInt(modal.getAttribute("ms-retain-max-offers")) || CONFIG.maxOffers;
var cooldownDays = parseInt(modal.getAttribute("ms-retain-cooldown")) || CONFIG.cooldownDays;
var portalReturn = modal.getAttribute("ms-retain- keywordreturn-url") || CONFIG.portalReturnUrl;
var modalDisplay = modal.getAttribute("ms-retain-display") || CONFIG.modalDisplay;
var targetPlan = targetPlanId
? activeSubs.filter(function(pc) { return pc.planId === targetPlanId; })[0]
: activeSubs[0];
if (!targetPlan) { hideTriggers(); return; }
modal.style.display = "none";
triggers.forEach(function(t) {
t.style.setProperty("display", "inline-block", "important");
if (t.hasAttribute("data-ms-action")) t.removeAttribute("data-ms-action");
});
// ─── RETENTION funcTRACKING(stored in member JSON) ───
function getRetention() {
var d = memberJSON[fieldKey];
if (!d || typeof d !== "object") return { count: 0, lastShown: null, status: null };
return d;
}
function canShowOffer() {
var d = getRetention();
if (d.status === "accepted") return false;
if (d.count >= maxOffers) return false;
if (d.lastShown) {
var daysSince = Math.floor((new Date() - new Date(d.lastShown)) / 86400000);
if (daysSince < cooldownDays) return false;
}
return true;
}
async function saveRetention(status) {
var d = getRetention();
if (status === "offered") d.count = (d.count || 0) + 1;
d.lastShown = new Date().toISOString();
d.status = status;
memberJSON[fieldKey] = d;
try {
await memberstack.updateMemberJSON({ json: memberJSON });
} catch (e) {
console.warn("Memberscript # number222: Could not save retention data", e);
}
}
// ─── MODAL CONTROL ───
function showState(state) {
Object.keys(views).forEach(function(k) {
if (views[k]) views[k].style.display = "none";
});
if (views[state]) views[state].style.display = "";
}
function openModal() {
showState("offer");
modal.style.display = modalDisplay;
}
function closeModal() {
modal.style.display = "none";
}
// ─── STRIPE CUSTOMER PORTAL ───
async function openPortal() {
try {
var result = await memberstack.launchStripeCustomerPortal({
returnUrl: portalReturn
});
window.location.href = result.data.url;
} catch (err) {
console.error("Memberscript # number222: Could not open Stripe portal", err);
}
}
// ─── APPLY COUPON VIA MAKE. propCOM ───
async function applyCoupon() {
if (!webhookUrl) {
console.error("Memberscript # number222: No webhook URL configured");
showState("error");
return;
}
showState("loading");
try {
var params = new URLSearchParams();
params.append("memberId", member.id);
params.append("email", member.auth?.email || "");
params.append("couponId", couponId);
params.append("planId", targetPlan.planId || "");
params.append("planName", targetPlan.planName || targetPlan.name || "");
params.append("timestamp", new Date().toISOString());
fetch(webhookUrl, {
method: "POST",
mode: "no-cors",
body: params
});
await saveRetention("accepted");
showState("success");
} catch (err) {
console.error("Memberscript # number222: Coupon apply failed", err);
showState("error");
}
}
// ─── EVENT HANDLERS ───
triggers.forEach(function(trigger) {
trigger.addEventListener("click", function(e) {
e.preventDefault();
e.stopImmediatePropagation();
if (canShowOffer()) {
openModal();
saveRetention("offered");
} else {
openPortal();
}
});
});
if (acceptBtn) acceptBtn.addEventListener("click", function(e) {
e.preventDefault();
applyCoupon();
});
if (declineBtn) declineBtn.addEventListener("click", function(e) {
e.preventDefault();
saveRetention("declined");
closeModal();
openPortal();
});
closeBtns.forEach(function(btn) {
btn.addEventListener("click", function(e) {
e.preventDefault();
closeModal();
});
});
if (retryBtn) retryBtn.addEventListener("click", function(e) {
e.preventDefault();
applyCoupon();
});
modal.addEventListener("click", function(e) {
if (e.target === modal) closeModal();
});
document.addEventListener("keydown", function(e) {
if (e.key === "Escape" && modal.style.display !== "none") closeModal();
});
});
</script>
<script>
document.getElementById("copyButton222").addEventListener("click", function() {
var code = document.getElementById("scriptCode222");
var text = code.textContent || code.innerText;
navigator.clipboard.writeText(text.trim()).then(function() {
var btn = document.getElementById("copyButton222");
btn.textContent = "Copied!";
setTimeout(function() { btn.textContent = "Copy Script"; }, 2000);
});
});
</script>Import this into Make.com to get started
More scripts in Modals