E-commerce Integration
The Membership Module integrates comprehensively with BigLedger’s CP-Commerce platform and other e-commerce systems, providing seamless online membership experiences including member portals, automatic points accrual on purchases, real-time redemption during checkout, and personalized shopping experiences based on tier status.
Integration Architecture
E-commerce integration operates through multiple touchpoints including customer account portal, shopping cart and checkout, order processing pipeline, customer communications, and administrative interfaces.
The integration follows a headless architecture pattern, separating backend membership services from frontend presentation. This approach allows brands to customize customer-facing experiences while maintaining standardized backend operations through the Membership API.
Member Portal Integration
Account Dashboard
The member portal provides a centralized dashboard where customers view their membership information, points balance, transaction history, tier status and benefits, and available rewards.
Dashboard Implementation:
async function loadMemberDashboard(memberId) {
// Fetch member data in parallel for fast loading
const [member, balance, transactions, rewards] = await Promise.all([
api.request('GET', `/members/${memberId}`),
api.request('GET', `/points/balance/${memberId}`),
api.request('GET', `/points/transactions/${memberId}?limit=10`),
api.request('GET', `/config/rewards?tier=${memberTier}`)
]);
return {
profile: {
name: `${member.data.firstName} ${member.data.lastName}`,
email: member.data.email,
memberId: member.data.memberId,
memberSince: member.data.joinDate
},
tier: {
current: member.data.tierName,
level: member.data.tier,
benefits: member.data.tierBenefits,
progress: calculateTierProgress(member.data)
},
points: {
current: balance.data.currentPoints,
lifetime: balance.data.lifetimePoints,
expiring: balance.data.expiringPoints,
expirationDate: balance.data.nextExpirationDate
},
recentTransactions: transactions.data,
availableRewards: filterAffordableRewards(rewards.data, balance.data.currentPoints)
};
}
function calculateTierProgress(member) {
const tierThresholds = {
'BRONZE': { next: 'SILVER', points: 1000 },
'SILVER': { next: 'GOLD', points: 5000 },
'GOLD': { next: 'PLATINUM', points: 15000 },
'PLATINUM': { next: null, points: null }
};
const current = tierThresholds[member.tier];
if (!current.next) {
return { isMaxTier: true };
}
const pointsToNext = current.points - member.lifetimePoints;
const progressPercentage = (member.lifetimePoints / current.points) * 100;
return {
nextTier: current.next,
pointsRequired: current.points,
pointsEarned: member.lifetimePoints,
pointsRemaining: pointsToNext,
progressPercentage: Math.min(progressPercentage, 100)
};
}Profile Management
Members can update their profile information through the portal:
async function updateMemberProfile(memberId, updates) {
// Validate updates before sending
const validatedUpdates = validateProfileUpdates(updates);
try {
const result = await api.request('PUT', `/members/${memberId}`, validatedUpdates);
// Update local session/cache
updateLocalSession(result.data);
return {
success: true,
message: 'Profile updated successfully',
data: result.data
};
} catch (error) {
return {
success: false,
message: 'Failed to update profile',
errors: parseAPIErrors(error)
};
}
}
function validateProfileUpdates(updates) {
const validated = {};
// Email validation
if (updates.email) {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(updates.email)) {
throw new Error('Invalid email format');
}
validated.email = updates.email;
}
// Phone validation
if (updates.phone) {
const phoneRegex = /^\+?[1-9]\d{1,14}$/;
if (!phoneRegex.test(updates.phone)) {
throw new Error('Invalid phone format');
}
validated.phone = updates.phone;
}
// Address validation
if (updates.address) {
validated.address = {
street: updates.address.street || '',
city: updates.address.city || '',
state: updates.address.state || '',
postalCode: updates.address.postalCode || '',
country: updates.address.country || 'Malaysia'
};
}
return validated;
}Transaction History
Members can view detailed transaction history with filtering and export capabilities:
async function loadTransactionHistory(memberId, filters = {}) {
const queryParams = new URLSearchParams({
limit: filters.limit || 50,
type: filters.type || '',
startDate: filters.startDate || '',
endDate: filters.endDate || ''
});
const result = await api.request(
'GET',
`/points/transactions/${memberId}?${queryParams}`
);
return result.data.map(txn => ({
date: formatDate(txn.processedAt),
type: formatTransactionType(txn.type),
description: txn.reason,
points: txn.points,
balance: txn.balanceAfter,
reference: txn.referenceId
}));
}
function formatTransactionType(type) {
const typeLabels = {
'earn': 'Points Earned',
'redeem': 'Points Redeemed',
'adjust': 'Adjustment',
'expire': 'Expired'
};
return typeLabels[type] || type;
}Shopping Cart Integration
Member Identification
When members log into the e-commerce site, their membership status is loaded and available throughout the shopping session:
async function initializeMemberSession(userId) {
// Map user account to member account
const memberMapping = await getMemberByUserId(userId);
if (memberMapping) {
const member = await api.request('GET', `/members/${memberMapping.memberId}`);
const balance = await api.request('GET', `/points/balance/${memberMapping.memberId}`);
// Store in session
return {
memberId: member.data.memberId,
tier: member.data.tier,
tierName: member.data.tierName,
points: balance.data.currentPoints,
benefits: member.data.tierBenefits
};
}
return null;
}Cart-Level Benefits
Membership tier may affect pricing, shipping, or promotions at the cart level:
function applyMemberBenefits(cart, memberSession) {
if (!memberSession) return cart;
// Apply tier-based discount
const tierDiscounts = {
'BRONZE': 0,
'SILVER': 5,
'GOLD': 10,
'PLATINUM': 15
};
const discountPercentage = tierDiscounts[memberSession.tier] || 0;
if (discountPercentage > 0) {
const discountAmount = cart.subtotal * (discountPercentage / 100);
cart.discounts.push({
type: 'tier_discount',
description: `${memberSession.tierName} Discount (${discountPercentage}%)`,
amount: discountAmount
});
cart.total -= discountAmount;
}
// Free shipping for premium tiers
if (['GOLD', 'PLATINUM'].includes(memberSession.tier)) {
cart.shippingCost = 0;
cart.benefits.push('Free shipping for ' + memberSession.tierName);
}
// Calculate points to be earned
const earnRate = 0.5;
const tierMultipliers = {
'BRONZE': 1.0,
'SILVER': 1.25,
'GOLD': 1.5,
'PLATINUM': 2.0
};
const multiplier = tierMultipliers[memberSession.tier] || 1.0;
const pointsToEarn = Math.floor(cart.total * earnRate * multiplier);
cart.pointsToEarn = pointsToEarn;
return cart;
}Checkout Integration
Points Earning Display
During checkout, display the points customers will earn from their purchase:
function renderPointsEarningPreview(orderTotal, memberSession) {
const earnRate = 0.5;
const tierMultiplier = getTierMultiplier(memberSession.tier);
const pointsToEarn = Math.floor(orderTotal * earnRate * tierMultiplier);
return {
message: `You will earn ${pointsToEarn} points from this purchase`,
details: {
basePoints: Math.floor(orderTotal * earnRate),
tierBonus: pointsToEarn - Math.floor(orderTotal * earnRate),
tierMultiplier: tierMultiplier
}
};
}Points Redemption
Allow customers to redeem points for discounts during checkout:
async function getCheckoutRedemptionOptions(memberId, orderTotal) {
const balance = await api.request('GET', `/points/balance/${memberId}`);
const rewards = await api.request('GET', '/config/rewards?category=voucher&available=true');
// Filter rewards member can afford
const affordableRewards = rewards.data.filter(reward =>
reward.pointsCost <= balance.data.currentPoints &&
reward.minimumPurchase <= orderTotal
);
return affordableRewards.map(reward => ({
rewardId: reward.rewardId,
name: reward.name,
pointsCost: reward.pointsCost,
discountAmount: reward.value,
description: reward.description,
canRedeem: true
}));
}
async function applyRedemptionToOrder(memberId, rewardId, orderId) {
try {
const redemption = await api.request('POST', '/points/redeem', {
memberId: memberId,
rewardId: rewardId,
referenceId: orderId,
reason: 'Order redemption'
});
return {
success: true,
pointsRedeemed: redemption.data.points,
discountAmount: redemption.data.rewardValue,
voucherCode: redemption.data.voucherCode,
newBalance: redemption.data.newBalance
};
} catch (error) {
if (error.response?.data?.error?.code === 'INSUFFICIENT_POINTS') {
return {
success: false,
error: 'Insufficient points for this redemption'
};
}
throw error;
}
}Checkout Flow
Complete checkout integration with membership:
async function processCheckoutWithMembership(orderData, memberSession) {
// 1. Validate member status
if (memberSession) {
const member = await api.request('GET', `/members/${memberSession.memberId}`);
if (member.data.status !== 'active') {
throw new Error('Member account is not active');
}
}
// 2. Apply tier benefits
if (memberSession) {
orderData = applyMemberBenefits(orderData, memberSession);
}
// 3. Process payment
const paymentResult = await processPayment(orderData);
if (!paymentResult.success) {
throw new Error('Payment failed');
}
// 4. Create order
const order = await createOrder(orderData, paymentResult);
// 5. Award points (if member)
if (memberSession && orderData.pointsToEarn > 0) {
try {
await api.request('POST', '/points/earn', {
memberId: memberSession.memberId,
points: orderData.pointsToEarn,
reason: 'Online purchase',
referenceId: order.orderId,
metadata: {
orderTotal: orderData.total,
itemCount: orderData.items.length
}
});
} catch (error) {
// Log but don't fail order if points award fails
console.error('Failed to award points:', error);
}
}
return {
success: true,
orderId: order.orderId,
pointsEarned: orderData.pointsToEarn || 0,
tierBenefitsApplied: memberSession ? true : false
};
}Order Processing Integration
Automatic Points Accrual
Points are automatically awarded when orders are completed and paid:
async function handleOrderCompleted(order) {
if (!order.memberId) return;
const earnRate = 0.5;
const member = await api.request('GET', `/members/${order.memberId}`);
const tierMultiplier = getTierMultiplier(member.data.tier);
const points = Math.floor(order.total * earnRate * tierMultiplier);
await api.request('POST', '/points/earn', {
memberId: order.memberId,
points: points,
reason: 'Online purchase',
referenceId: order.orderId,
metadata: {
orderTotal: order.total,
orderDate: order.createdAt,
itemCount: order.items.length
}
});
// Send confirmation email
await sendPointsEarnedEmail(order.memberId, points, order.orderId);
}Order Cancellation Handling
Reverse points when orders are cancelled:
async function handleOrderCancelled(order) {
if (!order.memberId || !order.pointsAwarded) return;
// Reverse points
await api.request('POST', '/points/adjust', {
memberId: order.memberId,
points: -order.pointsAwarded,
reason: 'Order cancellation',
referenceId: order.orderId,
adminNote: `Points reversed for cancelled order ${order.orderId}`
});
// Notify member
await sendPointsReversalEmail(order.memberId, order.pointsAwarded, order.orderId);
}Personalization
Tier-Based Content
Display personalized content based on membership tier:
function getPersonalizedContent(memberSession) {
if (!memberSession) {
return {
banner: 'Join our membership program to earn rewards!',
cta: 'Sign Up Now',
link: '/membership/register'
};
}
const tierContent = {
'BRONZE': {
banner: 'You are earning 1x points. Upgrade to Silver for 1.25x points!',
cta: 'Learn More',
link: '/membership/tiers'
},
'SILVER': {
banner: `Welcome ${memberSession.tierName}! Enjoy 5% discount on all purchases.`,
cta: 'View Benefits',
link: '/membership/benefits'
},
'GOLD': {
banner: `${memberSession.tierName} Member - Enjoy 10% discount and free shipping!`,
cta: 'Explore Rewards',
link: '/membership/rewards'
},
'PLATINUM': {
banner: `Welcome back, ${memberSession.tierName}! You have exclusive access to VIP products.`,
cta: 'Shop VIP Collection',
link: '/collections/vip'
}
};
return tierContent[memberSession.tier] || tierContent['BRONZE'];
}Product Recommendations
Personalize product recommendations based on membership data:
async function getPersonalizedRecommendations(memberId) {
const transactions = await api.request(
'GET',
`/points/transactions/${memberId}?limit=50&type=earn`
);
// Analyze purchase patterns
const categoryPreferences = analyzePurchaseHistory(transactions.data);
// Get tier-exclusive products
const member = await api.request('GET', `/members/${memberId}`);
const exclusiveProducts = await getProductsByTier(member.data.tier);
return {
basedOnHistory: recommendByCategory(categoryPreferences),
tierExclusive: exclusiveProducts,
trending: await getTrendingProducts()
};
}Email Integration
Order Confirmation with Points
Include membership information in order confirmation emails:
function generateOrderConfirmationEmail(order, memberSession) {
const emailTemplate = {
subject: `Order Confirmation - ${order.orderId}`,
sections: [
{
type: 'order_summary',
data: order
}
]
};
if (memberSession) {
emailTemplate.sections.push({
type: 'membership_summary',
data: {
pointsEarned: order.pointsEarned,
newBalance: memberSession.points + order.pointsEarned,
tier: memberSession.tierName,
benefits: memberSession.benefits
}
});
// Add expiring points warning if applicable
if (memberSession.expiringPoints > 0) {
emailTemplate.sections.push({
type: 'points_expiration_warning',
data: {
expiringPoints: memberSession.expiringPoints,
expirationDate: memberSession.expirationDate
}
});
}
}
return emailTemplate;
}Guest Checkout with Membership
Allow guests to earn points by providing membership credentials:
async function processGuestCheckoutWithMembership(orderData, membershipIdentifier) {
// Lookup member by email or phone
const members = await api.request(
'GET',
`/members?search=${membershipIdentifier}&limit=5`
);
if (members.data.length === 0) {
return {
memberFound: false,
message: 'No membership account found. Complete purchase to create one.'
};
}
if (members.data.length > 1) {
return {
memberFound: false,
message: 'Multiple accounts found. Please log in to continue.'
};
}
const member = members.data[0];
// Associate order with member
orderData.memberId = member.memberId;
orderData.memberSession = {
memberId: member.memberId,
tier: member.tier,
tierName: member.tierName
};
// Process with membership benefits
return await processCheckoutWithMembership(orderData, orderData.memberSession);
}Performance Optimization
Cache membership data in the session to reduce API calls:
class MembershipSessionCache {
constructor(sessionId) {
this.sessionId = sessionId;
this.cache = {};
this.ttl = 300000; // 5 minutes
}
async getMember(memberId) {
const cacheKey = `member_${memberId}`;
const cached = this.cache[cacheKey];
if (cached && Date.now() - cached.timestamp < this.ttl) {
return cached.data;
}
const member = await api.request('GET', `/members/${memberId}`);
this.cache[cacheKey] = {
data: member.data,
timestamp: Date.now()
};
return member.data;
}
invalidate(memberId) {
delete this.cache[`member_${memberId}`];
}
}Implement lazy loading for non-critical membership features and use CDN caching for static tier benefit information to ensure fast page loads and smooth shopping experiences.
Testing Scenarios
Test e-commerce integration thoroughly including guest checkout without membership, member login and automatic benefits application, points earning on order completion, points redemption during checkout, order cancellation and points reversal, tier upgrades during active sessions, and concurrent checkout sessions for the same member.
Use sandbox environment for comprehensive testing with realistic shopping scenarios before deploying to production.