Skip to main content

Understanding Bundle Configuration

Learn how bundle configuration works in Elastic Path, understand the data structures, and implement validation. For a practical implementation guide, see Configure Dynamic Bundles.

Configuration Structure

Bundle configuration defines which component options are selected and their quantities:

interface BundleConfiguration {
selected_options: {
[componentKey: string]: {
[optionId: string]: number; // Quantity
};
};
}

// Example configuration
const configuration: BundleConfiguration = {
selected_options: {
"processor": {
"prod-i9-uuid": 1
},
"graphics_card": {
"prod-rtx4080-uuid": 1
},
"storage": {
"prod-ssd-2tb-uuid": 2 // quantity of 2
},
"accessories": {
"prod-mouse-uuid": 1,
"prod-keyboard-uuid": 1
}
}
};

Key Concepts

Component Keys

  • Unique identifiers for each bundle component
  • Match the keys in bundle.attributes.components
  • Used as top-level properties in configuration

Option IDs

  • Product IDs that can be selected for each component
  • Must match available options in component definition
  • Used as keys within component configuration

Quantities

  • Number of each option selected
  • Must respect min/max constraints
  • Always stored as numbers

Validation

Validate configuration before API calls:

function validateConfiguration(
components: Components,
configuration: BundleConfiguration["selected_options"]
): { isValid: boolean; errors: string[] } {
const errors: string[] = [];

// Check each component's requirements
Object.entries(components).forEach(([componentKey, component]) => {
const selectedOptions = configuration[componentKey] || {};
const totalQuantity = Object.values(selectedOptions)
.reduce((sum, qty) => sum + Number(qty), 0);

// Validate minimum requirement
if (component.min && totalQuantity < component.min) {
errors.push(
`${component.name}: Select at least ${component.min} option(s)`
);
}

// Validate maximum requirement
if (component.max && totalQuantity > component.max) {
errors.push(
`${component.name}: Select at most ${component.max} option(s)`
);
}
});

return {
isValid: errors.length === 0,
errors
};
}

Configuration Persistence

Save configurations to improve user experience:

// Save to URL for sharing
function saveConfigurationToUrl(
bundleId: string,
configuration: BundleConfiguration["selected_options"]
) {
const configString = btoa(JSON.stringify(configuration));
const params = new URLSearchParams(window.location.search);
params.set('config', configString);

window.history.replaceState(
{},
'',
`${window.location.pathname}?${params.toString()}`
);
}

// Restore from URL
function restoreConfigurationFromUrl(): BundleConfiguration["selected_options"] | null {
const params = new URLSearchParams(window.location.search);
const configString = params.get('config');

if (!configString) return null;

try {
return JSON.parse(atob(configString));
} catch (error) {
console.warn('Invalid configuration in URL');
return null;
}
}

// Save to localStorage
function saveConfigurationToStorage(
bundleId: string,
configuration: BundleConfiguration["selected_options"]
) {
const key = `bundle_config_${bundleId}`;
localStorage.setItem(key, JSON.stringify({
configuration,
timestamp: Date.now()
}));
}

Using Configuration with SDK

Apply configuration when adding to cart:

// Configure bundle and get pricing
const configResponse = await configureByContextProduct({
path: { product_id: bundleId },
body: {
data: {
selected_options: configuration.selected_options
}
}
});

// Add to cart with configuration
await manageCarts({
path: { cartID: cartId },
body: {
data: {
type: 'cart_item',
id: bundleId,
quantity: 1,
bundle_configuration: configResponse.data?.meta?.bundle_configuration
}
}
});

Best Practices

  1. Always validate configuration before API calls
  2. Handle number types correctly for quantities
  3. Provide clear error messages for invalid configurations
  4. Consider persistence for better user experience
  5. Clean up stale data from storage periodically

Common Pitfalls

  • Not validating option IDs exist in component definition
  • Storing quantities as strings instead of numbers
  • Forgetting to check min/max constraints
  • Losing configuration on page refresh
  • Not handling invalid saved configurations gracefully

Next Steps

Now that you understand bundle configuration:

References