Skip to main content

Custom Pricing Integration

Mimeeq's custom pricing feature allows you to bypass the internal pricing system and implement your own pricing logic. This is essential for businesses with complex pricing rules, external ERP systems, or user-specific pricing requirements that go beyond standard price lists.

Why Use Custom Pricing?

Custom pricing is valuable when you need to:

  • Apply user-specific discounts - Different prices for VIP customers, employees, or partners
  • Use external authentication - Show different prices for logged-in users without using Mimeeq auth
  • Integrate with ERP/ecommerce - Pull prices from SAP, Dynamics, Shopify, or other systems
  • Implement complex rules - Volume discounts, promotional pricing, or time-based offers
  • Add dynamic markups - Calculate prices based on current costs, exchange rates, or market conditions

Business Value: Maintain a single source of truth for pricing while leveraging Mimeeq's powerful configuration and visualization capabilities.

How It Works

When custom pricing is enabled:

  1. Mimeeq's pricing engine is bypassed
  2. Your code listens for configuration changes
  3. You calculate or fetch the appropriate price
  4. You set the price using Mimeeq's API
  5. The configurator displays your custom price

Basic Implementation

Step 1: Enable Custom Pricing

In your embed template settings:

  1. Go to the template editor
  2. Find the "E-commerce" section
  3. Enable "Use Custom Pricing"
  4. Save the template

Step 2: Set Up Price Change Listener

document.addEventListener('mimeeq-price-change', async (event) => {
console.log('Price change event:', event.detail);

// Get configuration details
const { configurationCode, quantity } = event.detail;

// Calculate or fetch your custom price
const customPrice = await getCustomPrice(configurationCode, quantity);

// Apply the price to the configurator
window.mimeeqApp.utils.setPrice({
price: customPrice.total,
unitPrice: customPrice.unit,
currency: customPrice.currency,
vatType: 'INCL_VAT' // or 'EXCL_VAT'
});
});

Step 3: Implement Your Pricing Logic

async function getCustomPrice(configurationCode, quantity) {
// Your pricing logic here
// This could be a calculation, API call, or database lookup

return {
total: 1299.99 * quantity,
unit: 1299.99,
currency: 'USD'
};
}

Implementation Patterns

Pattern A: Adjusting Mimeeq's Base Price

This pattern is perfect when you want to use Mimeeq's pricing as a foundation and apply adjustments:

async function getCustomPrice(shortCode, quantity) {
try {
// First, get the base price from Mimeeq
const response = await fetch('https://mimeeqapi.com/get-product-price-info?' +
new URLSearchParams({
shortCode: shortCode,
quantity: quantity,
priceListGroup: 'public',
priceType: 'RRP'
}), {
headers: {
'X-API-KEY': 'your-api-key-here'
}
});

if (!response.ok) {
throw new Error('Failed to fetch base price');
}

const mimeeqPrice = await response.json();

// Apply your business logic
const userType = getUserType(); // Your function
let finalPrice = mimeeqPrice.price;

// Apply user-specific discounts
switch(userType) {
case 'vip':
finalPrice = finalPrice * 0.85; // 15% discount
break;
case 'dealer':
finalPrice = finalPrice * 0.70; // 30% discount
break;
case 'employee':
finalPrice = finalPrice * 0.60; // 40% discount
break;
}

// Apply quantity discounts
if (quantity >= 10) {
finalPrice = finalPrice * 0.95; // Additional 5% for bulk
}

return {
total: finalPrice,
unit: finalPrice / quantity,
currency: mimeeqPrice.currency
};

} catch (error) {
console.error('Error calculating price:', error);
// Return a fallback price or handle error appropriately
return {
total: 0,
unit: 0,
currency: 'USD'
};
}
}

Pattern B: Complete External Pricing

When prices come entirely from your system:

async function getCustomPrice(shortCode, quantity) {
try {
// Get product info to understand the configuration
const productInfo = await getProductInfo(shortCode);

// Call your pricing service
const response = await fetch('https://your-api.com/pricing', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + getAuthToken()
},
body: JSON.stringify({
sku: productInfo.SKU,
configuration: productInfo.configuration,
quantity: quantity,
customer: getCurrentCustomer(),
currency: getCurrency()
})
});

const priceData = await response.json();

return {
total: priceData.totalPrice,
unit: priceData.unitPrice,
currency: priceData.currency
};

} catch (error) {
console.error('External pricing failed:', error);
// Handle error - maybe fall back to Mimeeq pricing
return null;
}
}

async function getProductInfo(shortCode) {
const response = await fetch('https://mimeeqapi.com/get-product-info?' +
new URLSearchParams({ shortCode: shortCode }), {
headers: { 'X-API-KEY': 'your-api-key-here' }
});

return response.json();
}

Complete Working Example: User-Based Pricing

Here's a complete example that demonstrates user-based pricing with a mock service:

<!DOCTYPE html>
<html>
<head>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
margin: 0;
padding: 20px;
background: #f5f5f5;
}

.demo-container {
max-width: 1200px;
margin: 0 auto;
}

.user-selector {
background: white;
padding: 20px;
border-radius: 8px;
margin-bottom: 20px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}

.user-buttons {
display: flex;
gap: 10px;
margin-top: 10px;
}

.user-btn {
padding: 8px 16px;
border: 2px solid #e5e7eb;
background: white;
border-radius: 6px;
cursor: pointer;
transition: all 0.2s;
}

.user-btn:hover {
border-color: #3b82f6;
}

.user-btn.active {
background: #3b82f6;
color: white;
border-color: #3b82f6;
}

.price-info {
background: #fef3c7;
border: 1px solid #fbbf24;
padding: 15px;
border-radius: 6px;
margin-bottom: 20px;
display: none;
}

.price-info.show {
display: block;
}

.configurator-container {
background: white;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}

.loading-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(255,255,255,0.9);
display: flex;
align-items: center;
justify-content: center;
z-index: 9999;
display: none;
}

.loading-overlay.show {
display: flex;
}

.spinner {
width: 40px;
height: 40px;
border: 3px solid #f3f4f6;
border-top-color: #3b82f6;
border-radius: 50%;
animation: spin 1s linear infinite;
}

@keyframes spin {
to { transform: rotate(360deg); }
}

.debug-panel {
position: fixed;
bottom: 20px;
right: 20px;
background: white;
border: 1px solid #e5e7eb;
border-radius: 8px;
padding: 15px;
font-size: 12px;
font-family: monospace;
max-width: 300px;
max-height: 200px;
overflow-y: auto;
}

.debug-entry {
margin-bottom: 5px;
padding-bottom: 5px;
border-bottom: 1px solid #f3f4f6;
}
</style>
</head>
<body>
<div class="demo-container">
<!-- User Type Selector -->
<div class="user-selector">
<h3>Select User Type (Demo)</h3>
<p>Choose a user type to see different pricing:</p>
<div class="user-buttons">
<button class="user-btn active" data-user="public">Public User</button>
<button class="user-btn" data-user="registered">Registered (10% off)</button>
<button class="user-btn" data-user="vip">VIP (20% off)</button>
<button class="user-btn" data-user="dealer">Dealer (35% off)</button>
<button class="user-btn" data-user="employee">Employee (50% off)</button>
</div>
</div>

<!-- Price Information -->
<div class="price-info" id="price-info">
<strong>Custom Pricing Active:</strong> <span id="discount-info">Prices shown reflect your discount</span>
</div>

<!-- Configurator -->
<div class="configurator-container">
<mmq-embed
short-code="YOUR_PRODUCT_CODE"
template="custom_pricing_template">
</mmq-embed>
</div>
</div>

<!-- Loading Overlay -->
<div class="loading-overlay" id="loading">
<div class="spinner"></div>
</div>

<!-- Debug Panel -->
<div class="debug-panel" id="debug-panel">
<strong>Pricing Debug Log:</strong>
<div id="debug-log"></div>
</div>

<script src="https://cdn.mimeeq.com/read_models/embed/app-embed.js" async></script>

<script>
// Mock pricing service
class PricingService {
constructor() {
this.userType = 'public';
this.discounts = {
public: 0,
registered: 0.10,
vip: 0.20,
dealer: 0.35,
employee: 0.50
};

// Mock base prices (in real app, these would come from your system)
this.basePrices = {
default: 1299,
leather: 1599,
premium: 1899
};
}

setUserType(type) {
this.userType = type;
this.updateUI();
}

updateUI() {
// Update button states
document.querySelectorAll('.user-btn').forEach(btn => {
btn.classList.toggle('active', btn.dataset.user === this.userType);
});

// Update info message
if (this.userType !== 'public') {
document.getElementById('price-info').classList.add('show');
const discount = this.discounts[this.userType] * 100;
document.getElementById('discount-info').textContent =
`${this.userType.toUpperCase()} pricing: ${discount}% discount applied`;
} else {
document.getElementById('price-info').classList.remove('show');
}
}

async calculatePrice(configCode, quantity) {
// Simulate API delay
await new Promise(resolve => setTimeout(resolve, 300));

// Parse configuration to determine base price
let basePrice = this.basePrices.default;

if (configCode.includes('Material-leather')) {
basePrice = this.basePrices.leather;
} else if (configCode.includes('Material-premium')) {
basePrice = this.basePrices.premium;
}

// Apply user discount
const discount = this.discounts[this.userType];
const discountedPrice = basePrice * (1 - discount);

// Apply quantity discount
let quantityDiscount = 0;
if (quantity >= 5) quantityDiscount = 0.05;
if (quantity >= 10) quantityDiscount = 0.10;
if (quantity >= 20) quantityDiscount = 0.15;

const finalUnitPrice = discountedPrice * (1 - quantityDiscount);
const totalPrice = finalUnitPrice * quantity;

this.log(`Base: ${basePrice}, User: ${this.userType} (-${discount*100}%), Qty: ${quantity} (-${quantityDiscount*100}%), Final: ${finalUnitPrice.toFixed(2)}`);

return {
unit: finalUnitPrice,
total: totalPrice,
currency: 'USD',
breakdown: {
base: basePrice,
userDiscount: basePrice * discount,
quantityDiscount: discountedPrice * quantityDiscount,
savings: basePrice - finalUnitPrice
}
};
}

log(message) {
const logEl = document.getElementById('debug-log');
const entry = document.createElement('div');
entry.className = 'debug-entry';
entry.textContent = `[${new Date().toLocaleTimeString()}] ${message}`;
logEl.insertBefore(entry, logEl.firstChild);

// Keep only last 10 entries
while (logEl.children.length > 10) {
logEl.removeChild(logEl.lastChild);
}
}
}

// Initialize pricing service
const pricingService = new PricingService();

// Set up user type selector
document.querySelectorAll('.user-btn').forEach(btn => {
btn.addEventListener('click', () => {
pricingService.setUserType(btn.dataset.user);

// Trigger price recalculation
const event = new CustomEvent('user-changed');
document.dispatchEvent(event);
});
});

// Handle price change events
document.addEventListener('mimeeq-price-change', async (event) => {
pricingService.log('Price change event received');

// Use current values from observers
const configurationCode = window.currentConfigurationCode || event.detail.configurationCode;
const quantity = window.currentQuantity || event.detail.quantity || 1;

// Show loading
document.getElementById('loading').classList.add('show');

try {
// Calculate custom price
const priceData = await pricingService.calculatePrice(configurationCode, quantity);

// Apply to configurator
window.mimeeqApp.utils.setPrice({
price: priceData.total,
unitPrice: priceData.unit,
currency: priceData.currency,
vatType: 'INCL_VAT'
});

pricingService.log(`Price set: ${priceData.currency} ${priceData.unit.toFixed(2)}`);

} catch (error) {
console.error('Pricing error:', error);
pricingService.log(`Error: ${error.message}`);
} finally {
// Hide loading
document.getElementById('loading').classList.remove('show');
}
});

// Handle user changes
document.addEventListener('user-changed', () => {
// Trigger price recalculation with current configuration
const event = new CustomEvent('mimeeq-price-change', {
detail: {
configurationCode: 'pending', // Will be filled by price-change handler
quantity: 1
}
});
document.dispatchEvent(event);
});

// Initial setup when configurator loads
document.addEventListener('mimeeq-app-loaded', () => {
pricingService.log('Configurator loaded - Custom pricing active');

// Subscribe to configuration changes to always have current values
window.mimeeqApp.observers.product.configurationCode.subscribe(({ newValue }) => {
// Store current configuration for price calculations
window.currentConfigurationCode = newValue;
});

window.mimeeqApp.observers.product.quantity.subscribe(({ newValue }) => {
// Store current quantity for price calculations
window.currentQuantity = newValue || 1;
});
});
</script>
</body>
</html>

Complete Working Example: External System Integration

This example shows integration with an external pricing system:

<!DOCTYPE html>
<html>
<head>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
margin: 20px;
background: #f5f5f5;
}

.integration-demo {
max-width: 1200px;
margin: 0 auto;
}

.system-status {
background: white;
padding: 15px;
border-radius: 8px;
margin-bottom: 20px;
display: flex;
justify-content: space-between;
align-items: center;
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
}

.status-indicator {
display: flex;
align-items: center;
gap: 10px;
}

.status-dot {
width: 10px;
height: 10px;
border-radius: 50%;
background: #22c55e;
}

.status-dot.error {
background: #ef4444;
}

.price-source-toggle {
display: flex;
gap: 10px;
}

.toggle-btn {
padding: 6px 12px;
border: 1px solid #e5e7eb;
background: white;
border-radius: 6px;
cursor: pointer;
font-size: 14px;
}

.toggle-btn.active {
background: #3b82f6;
color: white;
border-color: #3b82f6;
}

.price-details {
background: white;
padding: 20px;
border-radius: 8px;
margin-bottom: 20px;
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
}

.price-row {
display: flex;
justify-content: space-between;
padding: 8px 0;
border-bottom: 1px solid #f3f4f6;
}

.price-row:last-child {
border-bottom: none;
font-weight: 600;
margin-top: 10px;
padding-top: 10px;
border-top: 2px solid #e5e7eb;
}

.api-log {
background: #1e293b;
color: #94a3b8;
padding: 15px;
border-radius: 8px;
font-family: monospace;
font-size: 12px;
max-height: 200px;
overflow-y: auto;
margin-bottom: 20px;
}

.log-entry {
margin-bottom: 8px;
display: flex;
gap: 10px;
}

.log-time {
color: #64748b;
}

.log-method {
color: #3b82f6;
min-width: 60px;
}

.log-status {
color: #22c55e;
}

.log-status.error {
color: #ef4444;
}
</style>
</head>
<body>
<div class="integration-demo">
<!-- System Status -->
<div class="system-status">
<div class="status-indicator">
<span class="status-dot" id="status-dot"></span>
<span>External Pricing System: <strong id="status-text">Connected</strong></span>
</div>
<div class="price-source-toggle">
<button class="toggle-btn active" data-source="external">External API</button>
<button class="toggle-btn" data-source="mimeeq">Mimeeq + Markup</button>
<button class="toggle-btn" data-source="fallback">Fallback Mode</button>
</div>
</div>

<!-- API Log -->
<div class="api-log" id="api-log">
<div class="log-entry">
<span class="log-time">12:00:00</span>
<span class="log-method">INIT</span>
<span>Pricing system initialized</span>
</div>
</div>

<!-- Price Details -->
<div class="price-details" id="price-details" style="display: none;">
<h3 style="margin-top: 0;">Price Calculation Details</h3>
<div id="price-breakdown"></div>
</div>

<!-- Configurator -->
<div style="background: white; border-radius: 8px; overflow: hidden; box-shadow: 0 1px 3px rgba(0,0,0,0.1);">
<mmq-embed
short-code="YOUR_PRODUCT_CODE"
template="custom_pricing_template">
</mmq-embed>
</div>
</div>

<script src="https://cdn.mimeeq.com/read_models/embed/app-embed.js" async></script>

<script>
// Mock External Pricing API
class ExternalPricingAPI {
constructor() {
this.baseUrl = 'https://api.example.com';
this.apiKey = 'mock-api-key';
this.source = 'external';
this.failureRate = 0.1; // 10% failure rate for demo
}

setSource(source) {
this.source = source;
this.log('CONFIG', `Switched to ${source} pricing`);
}

async getPrice(productData) {
this.log('REQUEST', `Getting price for ${productData.sku || 'product'}`);

// Simulate API delay
await new Promise(resolve => setTimeout(resolve, 500 + Math.random() * 500));

// Simulate occasional failures
if (this.source === 'external' && Math.random() < this.failureRate) {
this.log('ERROR', 'External API timeout', true);
throw new Error('External API timeout');
}

let priceData;

switch(this.source) {
case 'external':
priceData = await this.getExternalPrice(productData);
break;
case 'mimeeq':
priceData = await this.getMimeeqWithMarkup(productData);
break;
case 'fallback':
priceData = this.getFallbackPrice(productData);
break;
}

this.log('SUCCESS', `Price calculated: ${priceData.currency} ${priceData.unitPrice}`);
return priceData;
}

async getExternalPrice(productData) {
// Mock external system response
const basePrice = 999;
const optionPrices = {
'leather': 300,
'fabric': 0,
'velvet': 150,
'large': 200,
'medium': 100,
'small': 0
};

let totalPrice = basePrice;

// Add option prices
productData.configuration.forEach(block => {
block.options.forEach(option => {
const optionKey = option.toLowerCase();
if (optionPrices[optionKey]) {
totalPrice += optionPrices[optionKey];
}
});
});

// Quantity discounts
let discount = 0;
if (productData.quantity >= 5) discount = 0.05;
if (productData.quantity >= 10) discount = 0.10;

const discountedPrice = totalPrice * (1 - discount);

return {
unitPrice: discountedPrice,
totalPrice: discountedPrice * productData.quantity,
currency: 'USD',
breakdown: {
base: basePrice,
options: totalPrice - basePrice,
quantityDiscount: totalPrice * discount,
source: 'External ERP System'
}
};
}

async getMimeeqWithMarkup(productData) {
// Get Mimeeq price (mocked here)
const mimeeqPrice = 1200;
const markup = 1.25; // 25% markup
const markedUpPrice = mimeeqPrice * markup;

return {
unitPrice: markedUpPrice,
totalPrice: markedUpPrice * productData.quantity,
currency: 'USD',
breakdown: {
mimeeqPrice: mimeeqPrice,
markup: `${((markup - 1) * 100).toFixed(0)}%`,
source: 'Mimeeq + Company Markup'
}
};
}

getFallbackPrice(productData) {
// Simple fallback calculation
const price = 1500;

return {
unitPrice: price,
totalPrice: price * productData.quantity,
currency: 'USD',
breakdown: {
note: 'Using fallback pricing due to system unavailability',
source: 'Fallback Price List'
}
};
}

log(method, message, isError = false) {
const logEl = document.getElementById('api-log');
const entry = document.createElement('div');
entry.className = 'log-entry';

const time = new Date().toLocaleTimeString();
entry.innerHTML = `
<span class="log-time">${time}</span>
<span class="log-method">${method}</span>
<span class="${isError ? 'log-status error' : ''}">${message}</span>
`;

logEl.appendChild(entry);
logEl.scrollTop = logEl.scrollHeight;

// Update status indicator
if (isError) {
document.getElementById('status-dot').classList.add('error');
document.getElementById('status-text').textContent = 'Error';
setTimeout(() => {
document.getElementById('status-dot').classList.remove('error');
document.getElementById('status-text').textContent = 'Connected';
}, 3000);
}
}
}

// Initialize external API
const pricingAPI = new ExternalPricingAPI();

// Price source toggle
document.querySelectorAll('.toggle-btn').forEach(btn => {
btn.addEventListener('click', () => {
document.querySelectorAll('.toggle-btn').forEach(b => b.classList.remove('active'));
btn.classList.add('active');
pricingAPI.setSource(btn.dataset.source);

// Trigger price recalculation with stored values
if (window.currentConfigCode) {
const event = new CustomEvent('mimeeq-price-change', {
detail: {
configurationCode: window.currentConfigCode,
quantity: window.currentQty || 1
}
});
document.dispatchEvent(event);
}
});
});

// Handle price changes
document.addEventListener('mimeeq-price-change', async (event) => {
const { configurationCode, quantity } = event.detail;

try {
// Get product info for external system
const productData = {
sku: window.currentSku || 'UNKNOWN',
configuration: parseConfiguration(configurationCode),
quantity: quantity
};

// Get price from external system
const priceData = await pricingAPI.getPrice(productData);

// Apply to configurator
window.mimeeqApp.utils.setPrice({
price: priceData.totalPrice,
unitPrice: priceData.unitPrice,
currency: priceData.currency,
vatType: 'INCL_VAT'
});

// Show breakdown
showPriceBreakdown(priceData);

} catch (error) {
console.error('Pricing error:', error);

// Try fallback
if (pricingAPI.source === 'external') {
pricingAPI.log('WARN', 'Switching to fallback pricing');
pricingAPI.setSource('fallback');

// Retry with fallback
const fallbackData = pricingAPI.getFallbackPrice({
configuration: parseConfiguration(configurationCode),
quantity: quantity
});

window.mimeeqApp.utils.setPrice({
price: fallbackData.totalPrice,
unitPrice: fallbackData.unitPrice,
currency: fallbackData.currency,
vatType: 'INCL_VAT'
});

showPriceBreakdown(fallbackData);
}
}
});

// Helper function to parse configuration
function parseConfiguration(configCode) {
const parts = configCode.split('&');
return parts.map(part => {
const [block, option] = part.split('-');
return {
block: block,
options: [option]
};
});
}

// Show price breakdown
function showPriceBreakdown(priceData) {
const detailsEl = document.getElementById('price-details');
const breakdownEl = document.getElementById('price-breakdown');

detailsEl.style.display = 'block';

let html = '';
Object.entries(priceData.breakdown).forEach(([key, value]) => {
const label = key.charAt(0).toUpperCase() + key.slice(1).replace(/([A-Z])/g, ' $1');
html += `
<div class="price-row">
<span>${label}:</span>
<span>${typeof value === 'number' ? `$${value.toFixed(2)}` : value}</span>
</div>
`;
});

html += `
<div class="price-row">
<span>Final Unit Price:</span>
<span>${priceData.currency} ${priceData.unitPrice.toFixed(2)}</span>
</div>
`;

breakdownEl.innerHTML = html;
}

// Initial setup
document.addEventListener('mimeeq-app-loaded', () => {
pricingAPI.log('READY', 'Custom pricing system active');

// Store current values for price calculations
window.mimeeqApp.observers.product.configurationCode.subscribe(({ newValue }) => {
window.currentConfigCode = newValue;
});

window.mimeeqApp.observers.product.quantity.subscribe(({ newValue }) => {
window.currentQty = newValue || 1;
});

window.mimeeqApp.observers.product.sku.subscribe(({ newValue }) => {
window.currentSku = newValue;
});
});
</script>
</body>
</html>

Using Mimeeq's Backend API

When implementing Pattern A (adjusting Mimeeq prices), you'll need to use the backend API:

API Parameters

The /get-product-price-info endpoint accepts these parameters:

  • shortCode (required) - Configuration short code
  • quantity (required) - Number of units
  • priceListGroup - Public price list to use
  • companyId - For company-specific pricing
  • templateId - Use template's price list
  • priceType - RRP, SALE, or COST
  • vatType - INCL_VAT or EXCL_VAT

Priority Order

If multiple parameters are provided:

  1. companyId (highest priority)
  2. priceListIds
  3. priceListGroup
  4. templateId
  5. lang (lowest priority)

Example API Call

async function getMimeeqPrice(shortCode, quantity, options = {}) {
const params = new URLSearchParams({
shortCode: shortCode,
quantity: quantity,
...options
});

const response = await fetch(`https://mimeeqapi.com/get-product-price-info?${params}`, {
headers: {
'X-API-KEY': 'your-api-key',
'Content-Type': 'application/json'
}
});

if (!response.ok) {
throw new Error(`API error: ${response.status}`);
}

return response.json();
}

// Usage examples
const publicPrice = await getMimeeqPrice(shortCode, 1, {
priceListGroup: 'public'
});

const dealerPrice = await getMimeeqPrice(shortCode, 1, {
priceListGroup: 'dealer',
priceType: 'COST'
});

const companyPrice = await getMimeeqPrice(shortCode, 1, {
companyId: 'company-123',
priceType: 'RRP'
});

Best Practices

Error Handling

Always implement robust error handling:

document.addEventListener('mimeeq-price-change', async (event) => {
try {
const price = await getCustomPrice(event.detail.configurationCode, event.detail.quantity);

if (!price || typeof price.total !== 'number') {
throw new Error('Invalid price data');
}

window.mimeeqApp.utils.setPrice(price);

} catch (error) {
console.error('Pricing failed:', error);

// Option 1: Show error to user
showPricingError('Unable to calculate price. Please try again.');

// Option 2: Use fallback price
window.mimeeqApp.utils.setPrice({
price: 0,
unitPrice: 0,
currency: 'USD',
error: true
});

// Option 3: Retry with exponential backoff
retryPricing(event.detail);
}
});

Performance Optimization

// Debounce rapid configuration changes
let priceTimeout;

document.addEventListener('mimeeq-price-change', (event) => {
clearTimeout(priceTimeout);
priceTimeout = setTimeout(() => {
handlePriceChange(event.detail);
}, 300); // Wait 300ms for changes to settle
});

// Cache prices for identical configurations
const priceCache = new Map();

async function getCachedPrice(configCode, quantity) {
const cacheKey = `${configCode}-${quantity}`;

if (priceCache.has(cacheKey)) {
return priceCache.get(cacheKey);
}

const price = await calculatePrice(configCode, quantity);
priceCache.set(cacheKey, price);

// Clear cache after 5 minutes
setTimeout(() => priceCache.delete(cacheKey), 5 * 60 * 1000);

return price;
}

Loading States

Provide feedback during price calculations:

let loadingElement;

document.addEventListener('mimeeq-price-change', async (event) => {
// Show loading state
showPriceLoading();

try {
const price = await getCustomPrice(event.detail);
window.mimeeqApp.utils.setPrice(price);
} finally {
// Always hide loading state
hidePriceLoading();
}
});

function showPriceLoading() {
// Option 1: Add loading class
document.body.classList.add('pricing-loading');

// Option 2: Show custom loading indicator
const loader = document.getElementById('price-loader');
if (loader) {
loader.style.display = 'block';
}
}

function hidePriceLoading() {
document.body.classList.remove('pricing-loading');

const loader = document.getElementById('price-loader');
if (loader) {
loader.style.display = 'none';
}
}

Common Issues and Solutions

Price not updating

  • Verify custom pricing is enabled in template
  • Check event listener is attached before configurator loads
  • Ensure setPrice is called with valid data

Price flashing or jumping

  • Implement debouncing for rapid changes
  • Set initial price immediately on load
  • Use loading states to mask calculations

External API failures

  • Implement retry logic with backoff
  • Have fallback pricing ready
  • Cache successful responses
  • Monitor API performance

Currency mismatch

  • Always specify currency in setPrice
  • Handle multi-currency scenarios
  • Match currency with Mimeeq's settings

Next Steps

Custom pricing gives you complete control over how products are priced in your configurator. Start with simple adjustments and gradually add sophistication as your needs grow.