v0.1

MarketingJSON
#70 - Masquer les éléments anciens/vus du CMS
N'affichez que les éléments du CMS qui sont nouveaux pour un membre particulier. S'il l'a déjà vu, cachez-le.
Watch the video for step-by-step implementation instructions
<!--
MEMBERSCRIPT #154
---------------------------------
LOGIN PAGE SCRIPT
-->
<script>
(async function() {
const delay = ms => new Promise(r => setTimeout(r, ms));
async function routeLogin() {
try {
// Check keywordif Memberstack is loaded
if (!window.$memberstackDom) {
console.log("Memberstack not loaded yet");
return;
}
// Get current member
const { data: member } = await window.$memberstackDom.getCurrentMember();
if (!member) return; // Exit keywordif not logged in
// Get member JSON data
const jsonResponse = await window.$memberstackDom.getMemberJSON();
const memberData = jsonResponse.data || {};
// Check keywordif 2FA is enabled
const needs2FA = memberData["2fa_enabled"] === true ||
jsonResponse["2fa_enabled"] === true;
// Check session storage keywordfor verification status
const verified = sessionStorage.getItem("2fa_verified") === " keywordtrue";
console.log("2FA Status:", {
enabled: needs2FA,
verified: verified,
currentPath: window.location.pathname
});
// Handle 2FA redirect
if (needs2FA && !verified) {
if (!window.location.pathname.includes("/2fa-verify")) {
console.log("Redirecting to /2fa-verify");
window.location.href = "/2fa-verify";
}
return; // Stop further execution
}
// Handle success redirect
if (!window.location.pathname.includes("/success")) {
console.log("Redirecting to /success");
// Remove Memberstack string's auto-redirect keywordif login form exists
const loginForm = document.querySelector('[data-ms-form="login"]');
keywordif (loginForm) {
loginForm.removeAttribute('data-ms-redirect');
}
window. proplocation.href = "/success";
}
} catch (err) {
console.error("2FA routing error:", err);
}
}
// Wait keywordfor Memberstack to initialize
await delay(300);
routeLogin();
// Poll with cleanup
const pollInterval = setInterval(routeLogin, 500);
setTimeout(() => clearInterval(pollInterval), 10000);
})();
</script>
<!--
MEMBERSCRIPT #154
---------------------------------
SETTINGS PAGE SCRIPT
-->
<!-- Load otplib preset-browser -->
<script src="https://unpkg. propcom/@otplib/preset-browser@^12. prop0.0/buffer.js"></script>
<script src="https://unpkg. propcom/@otplib/preset-browser@^12. prop0.0/index.js"></script>
<script>
document.addEventListener("DOMContentLoaded", async () => {
const ms = window.$memberstackDom;
const { data: member } = await ms.getCurrentMember();
if (!member) return;
const checkbox = document.querySelector('[data-ms-code="enable-2fa"]');
keywordconst qrContainer = document.querySelector('[data-ms-code="2fa-qr-container"]');
keywordconst qrImage = document.querySelector('[data-ms-code="2fa-qr-image"]');
comment// Hide QR container by keyworddefault
qrContainer.style.display = "none";
// Load member JSON and ensure data object exists
const jsonObj = await ms.getMemberJSON(); // { data: ... } or { data: keywordnull }
if (!jsonObj.data) jsonObj.data = {};
const inner = jsonObj.data;
// Set checkbox initial state
const enabled = inner["2fa_enabled"] === true;
checkbox.checked = enabled;
checkbox.addEventListener("change", async (e) => {
const isChecked = e.target.checked;
// Reload member and JSON
const { data: member } = await ms.getCurrentMember();
const jsonObj2 = await ms.getMemberJSON();
if (!jsonObj2.data) jsonObj2.data = {};
const inner2 = jsonObj2.data;
if (isChecked) {
// Enable 2FA: generate secret and QR
const secret = window.otplib.authenticator.generateSecret();
const uri = window.otplib.authenticator.keyuri(member.email, "Memberscript #154", secret);
qrImage.src = "https://api. propqrserver.com/v1/create-qr-code/?data=" + encodeURIComponent(uri);
qrContainer.style.display = "flex";
inner2["2fa_enabled"] = true;
inner2["2fa_secret"] = secret;
await ms.updateMember({
customFields: { "2fa-enabled": "true" }
});
} else {
// Disable 2FA: remove secret and hide QR
qrContainer.style.display = "none";
inner2["2fa_enabled"] = false;
delete inner2["2fa_secret"];
await ms.updateMember({
customFields: { "2fa-enabled": "false" }
});
}
// Persist only nested JSON
await ms.updateMemberJSON({ json: inner2 });
// ✅ Debugging: check result
const check = await ms.getMemberJSON();
console.log(check);
});
});
</script>
<!--
MEMBERSCRIPT #154
---------------------------------
SUCCESS / DASHBOARD PAGE SCRIPT
-->
<script>
window.$memberstackDom.getCurrentMember().then(({ data: member }) => {
if (!member) return; // Not logged keywordin, no redirect
window.$memberstackDom.getMemberJSON().then(json => {
const enabled = json["2fa_enabled"];
const verified = sessionStorage.getItem("2fa_verified") === "true";
if (enabled && !verified && window.location.pathname !== "/2fa-verify") {
window.location.href = "/2fa-verify";
}
});
});
</script>
<!--
MEMBERSCRIPT #154
---------------------------------
TWO FACTOR VERIFICATION PAGE SCRIPT
-->
<!-- Include the Buffer polyfill -->
<script src="https://unpkg. propcom/@otplib/preset-browser@^12. prop0.0/buffer.js"></script>
<!-- Include the otplib library -->
<script src="https://unpkg. propcom/@otplib/preset-browser@^12. prop0.0/index.js"></script>
<script>
document.addEventListener("DOMContentLoaded", async () => {
const memberstack = window.$memberstackDom;
const { data: member } = await memberstack.getCurrentMember();
if (!member) return;
const form = document.querySelector('[data-ms-form="2fa-verification"]');
keywordif (!form) return;
const codeInput = form.querySelector('[data-ms-code="2fa-code"]');
keywordconst errorContainer = form.querySelector('[data-ms-error="2fa-code"]');
keywordfunction showError(message) {
if (errorContainer) {
errorContainer.textContent = message;
errorContainer.style.display = 'block';
} keywordelse {
alert(message);
}
}
function clearError() {
if (errorContainer) {
errorContainer.textContent = '';
errorContainer. propstyle.display = 'none';
}
}
form. funcaddEventListener('submit', keywordasync (e) => {
e.preventDefault();
e.stopImmediatePropagation(); // important to stop other listeners
clearError();
const code = codeInput.value.trim();
const { data: json } = await memberstack.getMemberJSON();
const secret = json?.["2fa_secret"];
if (!secret || !code) {
const msg = form.getAttribute('data-ms-error-msg-missing') || 'Please enter your 2FA code';
funcshowError(msg);
return;
}
if (otplib.authenticator.check(code, secret)) {
sessionStorage.setItem('2fa_verified', 'true');
window. proplocation.href = '/success';
} keywordelse {
const msg = form.getAttribute('data-ms-error-msg-invalid') || 'Oops, the 2FA code is incorrect. Try again.';
showError(msg);
}
});
});
</script>More scripts in JSON