Skip to main content

Understanding the Variation Matrix

Learn how to work with Elastic Path's variation matrix, a powerful nested structure that maps product options to child product IDs. Master the matrix structure and implement robust product selection logic that handles any number of variations.

Understanding the Structure​

The variation matrix uses option IDs (not variation IDs) as keys. The structure depth depends on how many variations your product has:

Here's a real variation matrix structure:

{
"801eabad-5108-4991-9f98-1830252214eb": { // Black leather option ID
"8f749ee2-17fb-4876-963f-2f57c0dffd97": "ed971d72-ca0c-4472-86f9-db03227bebfd", // Small
"d536955b-afa3-40e4-88cc-f6ee0248eeea": "ca9791a6-5adb-4207-8ea3-5a5b3d58fc4f", // Medium
"bbd91e51-690b-4743-9eb7-185a5bb88a62": "86ffccbe-6dfa-4903-9861-27eaef046761", // Large
"a987256b-76d1-4dad-b59e-fcc1c6198d1f": "9df52c2e-a145-4ee5-9abe-2d2961fadd2d" // XL
},
"84fd8ba0-9829-4b79-bfe9-ffee1ab60b95": { // Chestnut leather option ID
"8f749ee2-17fb-4876-963f-2f57c0dffd97": "7ed766a9-7e1c-4fce-bfed-0455bf4c3af0", // Small
// ... more size options
}
// ... more color options
}

Key Concepts​

  1. Option IDs as Keys: The matrix uses option IDs directly, not variation IDs
  2. Nesting Order: Determined by how variations were configured (often alphabetical or creation order)
  3. Flexible Depth: 2 levels for 2 variations, 3 levels for 3 variations, etc.
  4. No Fixed Pattern: The first level could be Size or Color depending on your product setup

Implementation Approach: Recursive Lookup​

The most flexible approach is to use a recursive function that can handle any depth of nesting:

// Recursive function used by Elastic Path's Composable Frontend
export function getSkuIdFromOptions(
options: string[],
matrix: any
): string | undefined {
// Base case: if we've reached a child product ID (string)
if (typeof matrix === 'string') {
return matrix;
}

// Try each option as a key in the current matrix level
for (const currOption in options) {
const optionId = options[currOption];
const nestedMatrix = matrix[optionId];

if (nestedMatrix) {
// Recurse deeper into the matrix
return getSkuIdFromOptions(options, nestedMatrix);
}
}

return undefined;
}

// Usage example
const selectedOptions = [
'801eabad-5108-4991-9f98-1830252214eb', // Black leather
'8f749ee2-17fb-4876-963f-2f57c0dffd97' // Small size
];

const childProductId = getSkuIdFromOptions(selectedOptions, variationMatrix);
// Returns: 'ed971d72-ca0c-4472-86f9-db03227bebfd'

Why Use Recursive Lookup?​

  1. Handles Any Number of Variations: Works with 1, 2, 3+ variations without modification
  2. Order Agnostic: Doesn't need to know which variation is at which level
  3. Future Proof: Adapts to changes in how variations are structured
  4. Production Tested: Used in Elastic Path's official example implementation

Alternative: Direct Lookup (When You Know the Structure)​

If you know your matrix structure is always consistent (e.g., Color → Size), you can use direct lookup:

// Direct lookup when you know the structure
function getChildDirectly(
colorOptionId: string,
sizeOptionId: string,
matrix: any
): string | undefined {
return matrix[colorOptionId]?.[sizeOptionId];
}

// Much simpler, but less flexible
const childId = getChildDirectly(
'801eabad-5108-4991-9f98-1830252214eb', // Black
'8f749ee2-17fb-4876-963f-2f57c0dffd97', // Small
variationMatrix
);

Complete Example: From Selection to Cart​

Here's a full implementation showing how to use the recursive lookup:

import { getSkuIdFromOptions } from '@/utils/product-helper';

// Parent product with variations
const parentProduct = {
id: "a2c20cd6-5f34-47b6-9582-5044a5b50991",
meta: {
variations: [
{
id: "10a35688-d48e-4228-8bd2-b3b5f71c992d",
name: "Couch Size",
options: [
{ id: "8f749ee2-17fb-4876-963f-2f57c0dffd97", name: "Small" },
{ id: "d536955b-afa3-40e4-88cc-f6ee0248eeea", name: "Medium" }
]
},
{
id: "6cc91048-c351-4b35-aacd-8d613d515fa7",
name: "Leather Color",
options: [
{ id: "801eabad-5108-4991-9f98-1830252214eb", name: "Black" },
{ id: "84fd8ba0-9829-4b79-bfe9-ffee1ab60b95", name: "Chestnut" }
]
}
],
variation_matrix: {
"801eabad-5108-4991-9f98-1830252214eb": { // Black
"8f749ee2-17fb-4876-963f-2f57c0dffd97": "ed971d72-ca0c-4472-86f9-db03227bebfd", // Small
"d536955b-afa3-40e4-88cc-f6ee0248eeea": "ca9791a6-5adb-4207-8ea3-5a5b3d58fc4f" // Medium
},
"84fd8ba0-9829-4b79-bfe9-ffee1ab60b95": { // Chestnut
"8f749ee2-17fb-4876-963f-2f57c0dffd97": "7ed766a9-7e1c-4fce-bfed-0455bf4c3af0", // Small
"d536955b-afa3-40e4-88cc-f6ee0248eeea": "1478ea17-078c-4e3c-b3b0-d8400823a3ba" // Medium
}
}
}
};

// Component implementation
function VariationSelector({ parentProduct, onAddToCart }) {
const [selectedOptions, setSelectedOptions] = useState({});

const handleOptionSelect = (variationId: string, optionId: string) => {
setSelectedOptions(prev => ({
...prev,
[variationId]: optionId
}));
};

const handleAddToCart = () => {
// Get selected option IDs as an array
const optionIds = Object.values(selectedOptions);

// Use recursive lookup
const childId = getSkuIdFromOptions(
optionIds,
parentProduct.meta.variation_matrix
);

if (childId) {
onAddToCart(childId);
}
};

// Check if all variations have selections
const allSelected = parentProduct.meta.variations.every(
v => selectedOptions[v.id] !== undefined
);

return (
<div>
{/* Render variation options */}
{parentProduct.meta.variations.map(variation => (
<VariationOptions
key={variation.id}
variation={variation}
selectedId={selectedOptions[variation.id]}
onSelect={(optionId) => handleOptionSelect(variation.id, optionId)}
/>
))}

<button
disabled={!allSelected}
onClick={handleAddToCart}
>
Add to Cart
</button>
</div>
);
}

Key Takeaways​

Understanding the Variation Matrix​

  1. Structure: The matrix uses option IDs as keys, not variation IDs
  2. Nesting Order: Determined by product configuration, not predictable
  3. Depth: Equals the number of variations (2 variations = 2 levels deep)
  4. Values: The leaf nodes are always child product UUIDs

Best Practices​

  1. Use Recursive Lookup: The getSkuIdFromOptions function handles any variation structure
  2. Don't Assume Order: The matrix structure can vary between products
  3. Validate Selections: Ensure all variations have selections before lookup
  4. Handle Edge Cases: Check for undefined results and provide user feedback

Common Pitfalls to Avoid​

  1. Don't hardcode matrix structure - It varies by product
  2. Don't assume which variation is at which level - Use recursive lookup
  3. Don't forget to handle products with 1 or 3+ variations
  4. Don't mix up variation IDs with option IDs - The matrix uses option IDs

Next Steps​

References​

Ask External AI