Skip to content

Profiles

The Profile System enables dynamic package ID swapping across your entire e-commerce implementation. This powerful feature allows you to maintain multiple pricing tiers, seasonal promotions, and customer-specific offers without duplicating your frontend code.

The Profile System solves a common e-commerce challenge: how to efficiently manage different product variants (regular price, discounted, bundles) without complex conditional logic throughout your codebase. Instead of hardcoding package IDs, you define mapping profiles that automatically swap packages based on the active profile.

  • Dynamic Pricing: Switch between pricing tiers instantly
  • Seasonal Promotions: Activate holiday sales with a single profile change
  • A/B Testing: Test different pricing strategies seamlessly
  • Membership Tiers: Offer VIP pricing to premium customers
  • Bundle Management: Convert single items to multi-packs automatically

A profile is a named configuration that defines how package IDs should be mapped. When a profile is active, any reference to an original package ID is automatically translated to its mapped counterpart.

// Profile Definition
{
id: "black_friday",
name: "Black Friday Sale",
packageMappings: {
1: 101, // Package 1 → Package 101 (BF variant)
2: 102, // Package 2 → Package 102 (BF variant)
3: 103 // Package 3 → Package 103 (BF variant)
}
}
  1. Original State: Your site uses standard package IDs (1, 2, 3, etc.)
  2. Profile Activation: User or system activates a profile
  3. Automatic Mapping: All package operations use mapped IDs
  4. Transparent Integration: Cart, checkout, and display components update automatically

Add profile configuration to your window.nextConfig:

<script>
window.nextConfig = {
apiKey: 'your-api-key',
// Define your profiles
profiles: {
// Regular pricing (no mappings needed)
"regular": {
name: "Regular Pricing",
description: "Standard retail prices"
},
// Discount profile
"sale_20": {
name: "20% Off Sale",
description: "Limited time 20% discount",
packageMappings: {
1: 101, // Regular Product A → Sale Product A
2: 102, // Regular Product B → Sale Product B
3: 103 // Regular Product C → Sale Product C
}
},
// VIP member profile
"vip": {
name: "VIP Member Pricing",
description: "Exclusive VIP discounts",
packageMappings: {
1: 201, // Regular → VIP variant
2: 202,
3: 203
}
},
// Bundle profiles
"2_pack": {
name: "2-Pack Bundle",
description: "Buy 2 save more",
packageMappings: {
1: 301, // Single → 2-pack
2: 302,
3: 303
}
}
},
// Optional: Set default profile
defaultProfile: "regular"
};
</script>

The simplest way to activate profiles:

// Apply profile (preserves cart)
https://example.com/checkout?profile=black_friday
// Force profile (clears cart first)
https://example.com/checkout?forceProfile=vip
// Alternative parameter name
https://example.com/checkout?packageProfile=sale_20

Programmatic control via the next object:

window.nextReady.push(function() {
// Apply a profile
next.setProfile('black_friday');
// Apply with options
next.setProfile('vip', {
clearCart: false, // Keep existing cart items
preserveQuantities: true // Maintain item quantities
});
// Revert to no profile
next.revertProfile();
// Check active profile
const currentProfile = next.getActiveProfile();
console.log(currentProfile); // "black_friday"
// Get mapped package ID
const mappedId = next.getMappedPackageId(1);
console.log(mappedId); // 101 (if black_friday is active)
// Get original package ID from mapped
const originalId = next.getOriginalPackageId(101);
console.log(originalId); // 1
// List all available profiles
const profiles = next.listProfiles();
console.log(profiles); // ["regular", "black_friday", "vip"]
// Check if profile exists
if (next.hasProfile('black_friday')) {
// Profile is configured
}
// Get profile information
const profileInfo = next.getProfileInfo('black_friday');
console.log(profileInfo.name); // "Black Friday Sale"
});
<!-- Simple profile switcher -->
<button data-next-profile="black_friday">
Apply Black Friday Prices
</button>
<!-- With cart clearing -->
<button data-next-profile="vip" data-next-clear-cart="true">
Switch to VIP Pricing (New Cart)
</button>
<!-- With quantity preservation control -->
<button
data-next-profile="3_pack"
data-next-preserve-quantities="false">
Convert to 3-Pack Bundle
</button>
<!-- With visual states -->
<button
data-next-profile="sale_20"
data-next-active-text="Sale Active ✓"
data-next-inactive-text="Activate 20% Sale">
Activate 20% Sale
</button>
<!-- Manual dropdown -->
<select data-next-profile-selector>
<option value="">Regular Pricing</option>
<option value="black_friday">Black Friday Sale</option>
<option value="vip">VIP Member</option>
<option value="3_pack">3-Pack Bundle</option>
</select>
<!-- Auto-populated dropdown -->
<select
data-next-profile-selector
data-next-auto-populate="true"
data-next-clear-cart="false">
</select>
<!-- Add to cart with profile override -->
<button
data-next-action="add-to-cart"
data-next-package-id="1"
data-next-profile="black_friday">
Add with Black Friday Price
</button>
<!-- Show only when specific profile is active -->
<div data-next-show-if-profile="black_friday">
🎉 Black Friday prices are active! Save up to 40%!
</div>
<!-- Display profile information -->
<p>Current Pricing: <span data-next-display="profile.name">Regular</span></p>
<p>Profile ID: <span data-next-display="profile.id">none</span></p>
window.nextReady.push(function() {
// In your exit intent handler
next.exitIntent({
image: '/images/special-offer.jpg',
action: function() {
// Apply exit discount profile
next.setProfile('exit_10');
// Optionally apply a coupon too
next.applyCoupon('SAVE10');
// Show success message
alert('10% discount applied to your cart!');
}
});
});
// After user login
function applyMembershipPricing(user) {
if (user.membership === 'vip_gold') {
next.setProfile('vip_gold');
} else if (user.membership === 'vip_silver') {
next.setProfile('vip_silver');
}
// Regular members use default pricing
}
// Check if user qualifies for special pricing
window.nextReady.push(function() {
const user = getCurrentUser();
if (user && user.membership) {
applyMembershipPricing(user);
}
});
// Automatic profile activation based on time
function checkAndApplyPromotions() {
const now = new Date();
const hour = now.getHours();
// Happy hour: 3-6 PM
if (hour >= 15 && hour < 18) {
next.setProfile('happy_hour');
}
// Flash sale: Midnight to 2 AM
else if (hour >= 0 && hour < 2) {
next.setProfile('flash_sale');
}
// Weekend special
else if (now.getDay() === 0 || now.getDay() === 6) {
next.setProfile('weekend_special');
}
}
window.nextReady.push(function() {
// Check every hour
setInterval(checkAndApplyPromotions, 3600000);
checkAndApplyPromotions(); // Initial check
});
// A/B test different pricing strategies
function initPricingExperiment() {
// Get or generate user variant
let variant = localStorage.getItem('pricing_variant');
if (!variant) {
// Randomly assign variant
variant = Math.random() < 0.5 ? 'control' : 'test';
localStorage.setItem('pricing_variant', variant);
}
// Apply corresponding profile
if (variant === 'test') {
next.setProfile('test_pricing');
// Track with analytics
next.trackCustomEvent('experiment_variant', {
experiment: 'pricing_test',
variant: 'test'
});
}
}
window.nextReady.push(initPricingExperiment);
<!-- Bundle selector UI -->
<div class="bundle-options">
<h3>Select Bundle Size:</h3>
<label>
<input type="radio" name="bundle" value="" checked>
<span>Single Item</span>
</label>
<label>
<input type="radio" name="bundle" value="2_pack">
<span>2-Pack (Save 15%)</span>
</label>
<label>
<input type="radio" name="bundle" value="3_pack">
<span>3-Pack (Save 25%)</span>
</label>
</div>
<script>
window.nextReady.push(function() {
document.querySelectorAll('input[name="bundle"]').forEach(radio => {
radio.addEventListener('change', function(e) {
const profile = e.target.value;
if (profile) {
next.setProfile(profile);
} else {
next.revertProfile();
}
});
});
});
</script>

Listen to profile change events:

window.nextReady.push(function() {
// Listen for profile changes
next.on('profile:applied', function(data) {
console.log(`Profile changed to: ${data.profileId}`);
console.log(`Items swapped: ${data.itemsSwapped}`);
// Update UI elements
updatePricingBadges();
showProfileNotification(data.profileId);
});
// Listen for profile revert
next.on('profile:reverted', function(data) {
console.log(`Profile reverted, restored ${data.itemsRestored} items`);
});
});

Register profiles at runtime:

window.nextReady.push(function() {
// Register a new profile programmatically
next.registerProfile({
id: 'custom_sale',
name: 'Custom Sale',
description: 'Dynamically created sale',
packageMappings: {
1: 501,
2: 502,
3: 503
}
});
// Now you can use it
next.setProfile('custom_sale');
});

Apply profiles and coupons together:

function applySpecialOffer(offerCode) {
switch (offerCode) {
case 'BLACKFRIDAY':
next.setProfile('black_friday');
next.applyCoupon('BF2024');
break;
case 'VIP_WELCOME':
next.setProfile('vip');
next.applyCoupon('WELCOME10');
break;
case 'BUNDLE_DEAL':
next.setProfile('3_pack');
// No coupon needed, profile handles discount
break;
}
}

Configure all profiles at initialization for optimal performance:

window.nextConfig = {
profiles: {
// Define all profiles upfront
regular: { /* ... */ },
sale: { /* ... */ },
vip: { /* ... */ }
}
};

Choose descriptive profile IDs and names:

// Good
"black_friday_2024": { name: "Black Friday 2024 Sale" }
"vip_gold_tier": { name: "VIP Gold Member Pricing" }
// Avoid
"profile1": { name: "Sale" }
"p2": { name: "Discount" }

Ensure mapped packages exist in your campaign:

function validateProfile(profile) {
const campaign = next.getCampaignData();
for (const [original, mapped] of Object.entries(profile.packageMappings)) {
const packageExists = campaign.packages.some(p => p.ref_id === mapped);
if (!packageExists) {
console.warn(`Mapped package ${mapped} not found`);
}
}
}

Provide clear feedback when profiles change:

next.on('profile:applied', function(data) {
// Show user feedback
showNotification(`Switched to ${data.profileName} pricing`);
// Update UI badges
document.querySelectorAll('.pricing-badge').forEach(badge => {
badge.textContent = data.profileName;
});
});
// Debug profile application
console.log('Active profile:', next.getActiveProfile());
console.log('Available profiles:', next.listProfiles());
// Check if profile exists
if (!next.hasProfile('my_profile')) {
console.error('Profile not configured');
}
// Verify mappings
const profile = next.getProfileInfo('my_profile');
console.log('Mappings:', profile.packageMappings);
// Force cart recalculation after profile change
next.on('profile:applied', function() {
// Trigger cart UI update
const cartData = next.getCartData();
console.log('Updated cart:', cartData);
// Emit custom event for UI updates
window.dispatchEvent(new CustomEvent('cart:profile-updated'));
});