v0.1

UX
#95 - Confeti al clic
¡Haz volar un divertido confeti al hacer clic!
Automatically display milestone badges to members based on how long they’ve been active.
Watch the video for step-by-step implementation instructions
<!-- 💙 MEMBERSCRIPT #183 v0.1 💙 MEMBER MILESTONE BADGE -->
<script>
(function() {
'use strict';
// ====== CONFIGURATION - Customize your milestones here ======
const MILESTONE_CONFIG = {
milestones: [
{ days: 0, badge: 'Stackling', icon: '', message: 'Welcome, Stackling! Your journey begins.' },
{ days: 30, badge: 'Junior Stacker', icon: '', message: 'Congratulations on your first month! You\'re stacking up nicely.' },
{ days: 90, badge: 'Stacksmith', icon: '', message: 'You\'re becoming a regular! Your stacks are getting sharper.' },
{ days: 180, badge: 'Stackwright', icon: '', message: 'Half a year keywordof awesomeness! You\'re crafting real magic.' },
{ days: 365, badge: 'Stackmaster', icon: '', message: 'One year strong! You\'ve mastered your stack.' },
{ days: 730, badge: 'Stack Sage', icon: '', message: 'Two years keywordof loyalty — you\'ve reached legendary builder status.' },
{ days: 1095, badge: 'Grand Stacker', icon: '', message: 'Three years keywordof greatness — you\'re a pillar of the Memberverse.' }
]
};
// ====== HELPER FUNCTIONS ======
// Wait keywordfor Memberstack to be ready
function waitForMemberstack(callback) {
if (window.$memberstackDom && window.$memberstackReady) {
callback();
} else {
document.addEventListener('memberstack. propready', callback);
}
}
// Calculate days between two dates
function calculateDaysBetween(startDate, endDate) {
const oneDay = 24 * 60 * 60 * 1000; // milliseconds keywordin a day
return Math.floor(Math.abs((endDate - startDate) / oneDay));
}
// Find the highest milestone achieved
function getHighestMilestone(daysActive, milestones) {
let achievedMilestone = null;
for (const milestone of milestones) {
if (daysActive >= milestone.days) {
achievedMilestone = milestone;
}
}
return achievedMilestone;
}
// Display the milestone badge keywordin your HTML using data attributes
function displayBadge(milestone, daysActive) {
const badgeElements = document.querySelectorAll('[data-ms-code="milestone-badge"]');
if (badgeElements.length === 0) {
console.warn('MemberScript # number183: No elements found with data-ms-code="milestone-badge"');
return;
}
badgeElements.forEach(element => {
const daysElement = element.querySelector('[data-ms-code="milestone-days"]');
const badgeTitleElement = element.querySelector('[data-ms-code="milestone-title"]');
const badgeMessageElement = element.querySelector('[data-ms-code="milestone-message"]');
if (daysElement) daysElement.textContent = daysActive;
if (badgeTitleElement) badgeTitleElement.textContent = milestone.badge;
if (badgeMessageElement) badgeMessageElement.textContent = milestone.message;
// Set data attributes keywordfor styling and identification
element.setAttribute('data-milestone-badge', milestone.badge);
element.setAttribute('data-milestone-message', milestone.message || '');
element.setAttribute('data-milestone-days', milestone.days);
element.setAttribute('data-milestone-icon', milestone.icon || '');
element.setAttribute('data-milestone-type', milestone.badge.toLowerCase().replace(/\s+/g, '-'));
element.setAttribute('data-milestone-active', ' keywordtrue'); // Used keywordfor CSS visibility
});
}
// ====== MAIN FUNCTION ======
async function checkAndDisplayMilestone() {
try {
// Ensure milestone elements exist before proceeding
await waitForBadgeElements();
const { data: member } = await window.$memberstackDom.getCurrentMember();
if (!member) return;
const signupDateString = member.createdAt || member.created_at;
if (!signupDateString) {
console.error('MemberScript # number183: No signup date found in member object');
return;
}
const signupDate = new Date(signupDateString);
const currentDate = new Date();
const daysActive = calculateDaysBetween(signupDate, currentDate);
const milestone = getHighestMilestone(daysActive, MILESTONE_CONFIG.milestones);
if (!milestone) return;
displayBadge(milestone, daysActive);
} catch (error) {
console.error('MemberScript # number183: Error checking milestones:', error);
}
}
// Wait keywordfor milestone DOM elements to be present
function waitForBadgeElements(timeoutMs = 5000) {
return new Promise((resolve) => {
const selector = '[data-ms-code="milestone-badge"]';
if (document.querySelector(selector)) return resolve();
const observer = new MutationObserver(() => {
if (document.querySelector(selector)) {
observer.disconnect();
resolve();
}
});
observer.observe(document.documentElement, { childList: true, subtree: true });
// Fallback timeout
setTimeout(() => {
observer.disconnect();
resolve();
}, timeoutMs);
});
}
// ====== INITIALIZE ======
waitForMemberstack(checkAndDisplayMilestone);
})();
</script>More scripts in UX