Third-Party Integration
The Membership Module provides flexible integration capabilities for connecting with external systems including CRM platforms, marketing automation tools, analytics services, payment processors, and custom applications. These integrations enable comprehensive business ecosystems where membership data flows seamlessly across platforms.
Integration Patterns
Real-Time API Integration
Real-time integration uses synchronous API calls to exchange data immediately when events occur. This pattern is ideal for operations requiring instant feedback such as member validation at checkout, real-time points balance queries, immediate redemption processing, and live tier status verification.
Implementation Example:
// External system calls Membership API in real-time
async function validateMemberAtCheckout(memberId, externalSystemId) {
try {
const member = await membershipAPI.request('GET', `/members/${memberId}`);
if (member.data.status !== 'active') {
return {
valid: false,
reason: 'Member account is not active'
};
}
// Return member data for immediate use
return {
valid: true,
tier: member.data.tier,
points: member.data.points,
benefits: member.data.tierBenefits
};
} catch (error) {
console.error('Member validation failed:', error);
return {
valid: false,
reason: 'Unable to validate member'
};
}
}Webhook Integration
Webhooks enable event-driven integrations where the Membership Module pushes notifications to external systems when specific events occur. This pattern eliminates the need for constant polling and ensures external systems stay synchronized with membership data.
Supported Events:
member.created- New member account createdmember.updated- Member profile information changedmember.tier.changed- Member tier upgraded or downgradedpoints.earned- Points awarded to memberpoints.redeemed- Points redeemed by memberreward.claimed- Reward claimed by memberpoints.expiring- Points approaching expiration
Webhook Configuration:
// Register webhook endpoint with Membership API
async function registerWebhook(webhookURL, events) {
const webhookConfig = {
url: webhookURL,
events: events,
secret: generateWebhookSecret(),
active: true
};
const result = await membershipAPI.request('POST', '/webhooks', webhookConfig);
// Store webhook secret securely for signature verification
await storeWebhookSecret(result.data.webhookId, webhookConfig.secret);
return result.data;
}
// Example registration
const webhook = await registerWebhook(
'https://yourapp.com/webhooks/membership',
['member.created', 'points.earned', 'points.redeemed']
);Webhook Handler:
const express = require('express');
const crypto = require('crypto');
const app = express();
app.post('/webhooks/membership', express.json(), async (req, res) => {
// Verify webhook signature
const signature = req.headers['x-webhook-signature'];
const webhookSecret = await getWebhookSecret(req.body.webhookId);
const expectedSignature = crypto
.createHmac('sha256', webhookSecret)
.update(JSON.stringify(req.body))
.digest('hex');
if (signature !== expectedSignature) {
return res.status(401).json({ error: 'Invalid signature' });
}
// Process webhook event
const { eventType, data } = req.body;
try {
await processWebhookEvent(eventType, data);
res.status(200).json({ received: true });
} catch (error) {
console.error('Webhook processing failed:', error);
res.status(500).json({ error: 'Processing failed' });
}
});
async function processWebhookEvent(eventType, data) {
switch (eventType) {
case 'member.created':
await handleNewMember(data);
break;
case 'points.earned':
await handlePointsEarned(data);
break;
case 'points.redeemed':
await handlePointsRedeemed(data);
break;
case 'member.tier.changed':
await handleTierChange(data);
break;
}
}Batch Synchronization
Batch integration processes data in scheduled batches, suitable for non-time-sensitive operations such as daily member data synchronization, bulk points adjustments, nightly reporting and analytics, and periodic data backups.
Batch Export Example:
async function exportMemberDataBatch(startDate, endDate) {
const batchSize = 100;
let cursor = null;
const allMembers = [];
do {
const queryParams = new URLSearchParams({
limit: batchSize,
cursor: cursor || '',
startDate: startDate,
endDate: endDate
});
const result = await membershipAPI.request(
'GET',
`/members?${queryParams}`
);
allMembers.push(...result.data);
cursor = result.pagination.nextCursor;
} while (cursor);
return allMembers;
}
// Schedule daily batch export
async function scheduledDailyExport() {
const yesterday = new Date();
yesterday.setDate(yesterday.getDate() - 1);
const startDate = yesterday.toISOString().split('T')[0];
const endDate = new Date().toISOString().split('T')[0];
const members = await exportMemberDataBatch(startDate, endDate);
// Send to external system
await sendToCRM(members);
await sendToAnalytics(members);
console.log(`Exported ${members.length} member records`);
}CRM Integration
Customer Profile Synchronization
Synchronize membership data with CRM systems to maintain unified customer profiles:
async function syncMemberToCRM(memberId) {
// Fetch complete member profile
const [member, balance, transactions] = await Promise.all([
membershipAPI.request('GET', `/members/${memberId}`),
membershipAPI.request('GET', `/points/balance/${memberId}`),
membershipAPI.request('GET', `/points/transactions/${memberId}?limit=10`)
]);
// Map to CRM format
const crmContact = {
externalId: member.data.memberId,
firstName: member.data.firstName,
lastName: member.data.lastName,
email: member.data.email,
phone: member.data.phone,
customFields: {
membershipTier: member.data.tier,
membershipPoints: balance.data.currentPoints,
lifetimePoints: balance.data.lifetimePoints,
memberSince: member.data.joinDate,
lastActivity: transactions.data[0]?.processedAt
},
tags: [`membership-${member.data.tier.toLowerCase()}`]
};
// Update CRM
await crmAPI.upsertContact(crmContact);
}Bidirectional Sync
Maintain consistency between Membership Module and CRM:
class BidirectionalSync {
constructor(membershipAPI, crmAPI) {
this.membershipAPI = membershipAPI;
this.crmAPI = crmAPI;
}
// Sync from Membership to CRM
async syncMembershipToCRM(memberId) {
const member = await this.membershipAPI.request('GET', `/members/${memberId}`);
await this.crmAPI.updateContact(memberId, {
tier: member.data.tier,
points: member.data.points
});
}
// Sync from CRM to Membership
async syncCRMToMembership(contactId) {
const contact = await this.crmAPI.getContact(contactId);
if (contact.email || contact.phone) {
await this.membershipAPI.request('PUT', `/members/${contact.membershipId}`, {
email: contact.email,
phone: contact.phone,
address: contact.address
});
}
}
// Handle conflicts
async resolveConflict(memberId, membershipData, crmData) {
// Use timestamp-based conflict resolution
const membershipTimestamp = new Date(membershipData.updatedAt);
const crmTimestamp = new Date(crmData.updatedAt);
if (membershipTimestamp > crmTimestamp) {
await this.syncMembershipToCRM(memberId);
} else {
await this.syncCRMToMembership(crmData.id);
}
}
}Marketing Automation Integration
Segment Synchronization
Push membership segments to marketing automation platforms:
async function syncMembershipSegments() {
// Define segments
const segments = [
{
name: 'Gold Members',
filter: { tier: 'GOLD', status: 'active' }
},
{
name: 'High Points Balance',
filter: { minPoints: 5000, status: 'active' }
},
{
name: 'Inactive Members',
filter: { daysSinceLastActivity: 90 }
}
];
for (const segment of segments) {
const members = await queryMemberSegment(segment.filter);
await marketingAPI.createOrUpdateSegment({
name: segment.name,
members: members.map(m => ({
email: m.email,
memberId: m.memberId,
tier: m.tier,
points: m.points
}))
});
}
}
async function queryMemberSegment(filter) {
const queryParams = new URLSearchParams();
if (filter.tier) queryParams.append('tier', filter.tier);
if (filter.status) queryParams.append('status', filter.status);
const result = await membershipAPI.request('GET', `/members?${queryParams}`);
// Apply additional filters
let members = result.data;
if (filter.minPoints) {
members = members.filter(m => m.points >= filter.minPoints);
}
if (filter.daysSinceLastActivity) {
const cutoffDate = new Date();
cutoffDate.setDate(cutoffDate.getDate() - filter.daysSinceLastActivity);
members = members.filter(m =>
new Date(m.lastActivityDate) < cutoffDate
);
}
return members;
}Triggered Campaigns
Trigger marketing campaigns based on membership events:
async function handleTierUpgrade(data) {
const { memberId, previousTier, newTier } = data;
// Trigger congratulations email campaign
await marketingAPI.triggerCampaign({
campaignId: 'tier-upgrade-congratulations',
recipientEmail: data.email,
variables: {
firstName: data.firstName,
previousTier: previousTier,
newTier: newTier,
tierBenefits: data.tierBenefits
}
});
// Add to tier-specific segment
await marketingAPI.addToSegment(memberId, `membership-${newTier.toLowerCase()}`);
}
async function handlePointsExpiring(data) {
const { memberId, expiringPoints, expirationDate } = data;
if (expiringPoints >= 500) {
await marketingAPI.triggerCampaign({
campaignId: 'points-expiring-reminder',
recipientEmail: data.email,
variables: {
firstName: data.firstName,
expiringPoints: expiringPoints,
expirationDate: formatDate(expirationDate),
redeemURL: `https://shop.example.com/rewards?member=${memberId}`
}
});
}
}Analytics Integration
Event Tracking
Send membership events to analytics platforms:
async function trackMembershipEvent(eventType, data) {
const analyticsEvent = {
eventName: eventType,
timestamp: new Date().toISOString(),
userId: data.memberId,
properties: {
tier: data.tier,
points: data.points,
tierName: data.tierName
}
};
// Send to multiple analytics platforms
await Promise.all([
sendToGoogleAnalytics(analyticsEvent),
sendToMixpanel(analyticsEvent),
sendToSegment(analyticsEvent)
]);
}
async function sendToGoogleAnalytics(event) {
// Google Analytics 4 Measurement Protocol
await fetch('https://www.google-analytics.com/mp/collect', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
client_id: event.userId,
events: [{
name: event.eventName,
params: event.properties
}]
})
});
}Customer Lifetime Value Calculation
Integrate membership data for CLV analysis:
async function calculateMemberCLV(memberId) {
const [member, transactions] = await Promise.all([
membershipAPI.request('GET', `/members/${memberId}`),
membershipAPI.request('GET', `/points/transactions/${memberId}?type=earn&limit=1000`)
]);
// Calculate total spend (assuming 1 point = 2 MYR spend)
const totalSpend = transactions.data
.filter(t => t.type === 'earn')
.reduce((sum, t) => sum + (t.points * 2), 0);
// Calculate average order value and frequency
const orderCount = transactions.data.length;
const avgOrderValue = totalSpend / orderCount;
// Calculate customer tenure
const joinDate = new Date(member.data.joinDate);
const tenureMonths = (Date.now() - joinDate.getTime()) / (1000 * 60 * 60 * 24 * 30);
// Simple CLV calculation
const avgOrdersPerMonth = orderCount / tenureMonths;
const projectedLifetimeMonths = 36; // 3-year projection
const clv = avgOrderValue * avgOrdersPerMonth * projectedLifetimeMonths;
return {
memberId: memberId,
totalSpend: totalSpend,
orderCount: orderCount,
avgOrderValue: avgOrderValue,
tenureMonths: tenureMonths,
avgOrdersPerMonth: avgOrdersPerMonth,
projectedCLV: clv,
tier: member.data.tier
};
}Payment Processing Integration
Payment Gateway Integration
Link membership benefits with payment processing:
async function processPaymentWithMembershipBenefits(paymentData, memberId) {
// Get member tier
const member = await membershipAPI.request('GET', `/members/${memberId}`);
// Apply tier-based payment benefits
const paymentConfig = {
amount: paymentData.amount,
currency: 'MYR',
metadata: {
memberId: memberId,
tier: member.data.tier
}
};
// Premium tiers get installment options
if (['GOLD', 'PLATINUM'].includes(member.data.tier)) {
paymentConfig.installmentOptions = [3, 6, 12];
}
// Process payment
const paymentResult = await paymentGateway.createPayment(paymentConfig);
return paymentResult;
}Single Sign-On Integration
OAuth Integration
Implement SSO for unified authentication:
async function authenticateWithSSO(ssoToken) {
// Verify SSO token with identity provider
const ssoUser = await identityProvider.verifyToken(ssoToken);
// Map SSO user to membership account
const member = await membershipAPI.request(
'GET',
`/members?email=${ssoUser.email}&limit=1`
);
if (member.data.length === 0) {
// Create membership account for new SSO user
const newMember = await membershipAPI.request('POST', '/members', {
firstName: ssoUser.firstName,
lastName: ssoUser.lastName,
email: ssoUser.email,
externalId: ssoUser.id
});
return {
authenticated: true,
memberId: newMember.data.memberId,
newAccount: true
};
}
return {
authenticated: true,
memberId: member.data[0].memberId,
newAccount: false
};
}Data Warehouse Integration
ETL Pipeline
Extract membership data for data warehouse:
async function extractMembershipData(startDate, endDate) {
// Extract members
const members = await exportMemberDataBatch(startDate, endDate);
// Extract transactions
const transactions = await extractTransactions(startDate, endDate);
// Transform to warehouse schema
const transformedData = {
members: members.map(m => ({
member_id: m.memberId,
first_name: m.firstName,
last_name: m.lastName,
email: m.email,
tier: m.tier,
join_date: m.joinDate,
current_points: m.points,
lifetime_points: m.lifetimePoints,
extracted_at: new Date().toISOString()
})),
transactions: transactions.map(t => ({
transaction_id: t.transactionId,
member_id: t.memberId,
transaction_type: t.type,
points: t.points,
processed_at: t.processedAt,
reference_id: t.referenceId,
extracted_at: new Date().toISOString()
}))
};
// Load to warehouse
await loadToWarehouse(transformedData);
}
async function extractTransactions(startDate, endDate) {
const allTransactions = [];
let cursor = null;
do {
const result = await membershipAPI.request(
'GET',
`/transactions?startDate=${startDate}&endDate=${endDate}&limit=100&cursor=${cursor || ''}`
);
allTransactions.push(...result.data);
cursor = result.pagination.nextCursor;
} while (cursor);
return allTransactions;
}Integration Testing
End-to-End Testing
Test complete integration flows:
describe('Third-Party Integration', () => {
test('should sync new member to CRM', async () => {
// Create member in Membership Module
const member = await membershipAPI.request('POST', '/members', {
firstName: 'Test',
lastName: 'User',
email: 'test@example.com'
});
// Wait for webhook to trigger CRM sync
await waitForWebhook('member.created', member.data.memberId);
// Verify member exists in CRM
const crmContact = await crmAPI.getContactByEmail('test@example.com');
expect(crmContact).toBeDefined();
expect(crmContact.externalId).toBe(member.data.memberId);
expect(crmContact.customFields.membershipTier).toBe('BRONZE');
});
test('should trigger marketing campaign on tier upgrade', async () => {
const memberId = 'MEM-TEST-001';
// Upgrade member tier
await membershipAPI.request('POST', '/tiers/assign', {
memberId: memberId,
tierId: 'GOLD'
});
// Verify campaign triggered
const campaigns = await marketingAPI.getTriggeredCampaigns(memberId);
expect(campaigns).toContainEqual(
expect.objectContaining({
campaignId: 'tier-upgrade-congratulations'
})
);
});
});Monitoring Integration Health
Integration Metrics
Track integration performance and reliability:
class IntegrationMonitor {
constructor() {
this.metrics = {
webhookDeliveries: { successful: 0, failed: 0 },
apiCalls: { successful: 0, failed: 0 },
syncOperations: { successful: 0, failed: 0 },
averageLatency: 0
};
}
recordWebhookDelivery(success, latency) {
if (success) {
this.metrics.webhookDeliveries.successful++;
} else {
this.metrics.webhookDeliveries.failed++;
}
this.updateLatency(latency);
}
recordAPICall(success, latency) {
if (success) {
this.metrics.apiCalls.successful++;
} else {
this.metrics.apiCalls.failed++;
}
this.updateLatency(latency);
}
updateLatency(latency) {
const total = this.metrics.apiCalls.successful + this.metrics.apiCalls.failed;
this.metrics.averageLatency =
(this.metrics.averageLatency * (total - 1) + latency) / total;
}
getHealthStatus() {
const totalWebhooks =
this.metrics.webhookDeliveries.successful + this.metrics.webhookDeliveries.failed;
const webhookSuccessRate = totalWebhooks > 0
? (this.metrics.webhookDeliveries.successful / totalWebhooks) * 100
: 100;
const totalAPICalls =
this.metrics.apiCalls.successful + this.metrics.apiCalls.failed;
const apiSuccessRate = totalAPICalls > 0
? (this.metrics.apiCalls.successful / totalAPICalls) * 100
: 100;
return {
healthy: webhookSuccessRate >= 95 && apiSuccessRate >= 95,
webhookSuccessRate: webhookSuccessRate.toFixed(2) + '%',
apiSuccessRate: apiSuccessRate.toFixed(2) + '%',
averageLatency: Math.round(this.metrics.averageLatency) + 'ms'
};
}
}These integration patterns and examples provide comprehensive guidance for connecting external systems with the Membership Module, enabling sophisticated business ecosystems and unified customer experiences across platforms.