A technical guide to ecommerce in Magnolia
Magnolia in just 12 minutes
Why not learn more about what Magnolia can do while you have a coffee?
Digital experience platforms are the talk of the town. The integrations within system landscapes form the technical basis for this and contribute to various factors. One factor here is an author experience that is as intuitive as it is seamless. In other words, an author/creator/marketer should only need to operate within a few systems, ideally just one system, and find all content creation options there. They should be able to use and combine data from different peripheral systems to create a target group for customer journeys.
Today we are focusing on the connection between Magnolia CMS and an ecommerce system. More specifically, how to get product data into Magnolia CMS. In addition to a fully comprehensive solution, Magnolia has also created a narrow solution that is independent of the connector and allows external systems to be integrated within components, content apps and many other starting points. The Magnolia JavaScript Framework and the JavaScript UI module are used for this purpose.
Let's carry on with something more practical.
The following requirements are given. An editor wants to integrate products (e.g. for a slider or list) into a page. The ecommerce system provides an API. The aim is to persist the product data or product references in Magnolia's JCR/DB in order to display them in the frontend (regardless of whether headless or classic). The following simple example shows how easy this is.
We use the product API from Fake Store API, Magnolia DX Core and the JavaScript UI module mentioned above. Within Magnolia we use Light Development.
Below is a code example for a dialog definition. This can be used within components or page properties.
#dialog definition
form:
implementationClass:
info.magnolia.ui.javascript.form.FormViewWithChangeListener
properties:
product:
label: Products from API
$type: javascriptField
fieldScript: /jsfields-lm/webresources/product-chooser.html
height: 40
This inserts a JavaScript field into the dialog. This field loads its own small application in the background, which communicates with Magnolia and can exchange data. Within the script field, we use the React app to display a product chooser, which retrieves data from the interface (FakeStore API), displays it and allows you to select individual products, which are then added to a list. Communication with Magnolia takes place via Event Listener.
Here you can see the entire script (CSS has been removed):
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<script
src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-
dom.production.min.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
// config for magnolia communication
let correlationId;
let value;
//init app and get data from magnolia
window.addEventListener('message', function (event) {
if (event.data.action === 'init') {
correlationId = event.data.correlationId;
value = JSON.parse(event.data.state.value || '{}');
const container = document.getElementById('root');
const root = ReactDOM.createRoot(container);
root.render(<Picker />);
}
},
false
);
//manipulate field height if the product list gets longer
function changeHeight() {
parent.window.postMessage(
{
action: 'changeHeight',
correlationId: correlationId,
value: (document.documentElement.offsetHeight + 30),
},
'*'
);
};
//picker react component
function Picker(props) {
const [productList, setProductList] = React.useState([]);
const [selectedProducts, setSelectedProducts] =
React.useState(VALUE?.selectedProducts || []);
//add product to list
const addProduct = (e) => {
let value = e.target.value;
let p = productList&& productList.find(e => e.id ===
parseInt(value));
setSelectedProducts((selectedProducts) ? [... selectedProducts, p] :
[]);
}
//delete product from list
const deleteProduct = (prodId) => {
setSelectedProducts(oldValues => {
return oldValues.filter(prod => prod.id !== prodId)
})
}
//get products from api to create a select box
React.useEffect(() => {
fetch('https://fakestoreapi.com/products')
.then((res) => res.json())
.then((json) => {
setProductList(json);
});
}, []);
//save data in magnolia jcr
React.useEffect(() => {
parent.window.postMessage(
{
action: 'changeValue',
correlationId: correlationId,
value: JSON.stringify({ selectedProducts }),
},
'*'
);
changeHeight();
}, [selectedProducts]);
//list and selected product cards
return (
<div>
<div>
<select class='plb' id='product-list-box'
onChange={addProduct}>
{productList.map((item, i) =>
(
<option value={item.id}>{item.title}</option>
)
)
}
</select>
</div>
<div>
{selectedProducts && (
<div id="products" className="products">
{ selectedProducts.map((product) => {
return <div className="product">
<div onClick={() =>
deleteProduct(product.id)} className="product-remove">X</div>
<img className="product-image"
src={product.image} />
<div className="product-
id">{product.id}</div>
<div className="product-
name">{product.title}</div>
</div>;
}) }
</div>
)}
</div>
</div>
)
};
</script>
</body>
</html>
It looks like this in the authoring interface:
A JSON object is stored in the JCR for precisely this purpose, so I can continue to use it in the frontend of my choice. Dependencies on price or item availability should not be stored in the CMS and should be synchronized with the ecommerce system via the frontend. This integration is a prime example and very simple, as no authentication etc. is required. But even more complex cases can be implemented with the JS field feature, i.e. an integration to Salesforce Commerce or even further into the Salesforce world of marketing automation and CRM.
But why are JS fields a powerful feature?
Flexibility
JS-Fields allow developers to quickly and easily connect APIs and use them within Magnolia. You are independent of the data structure or purpose, as JS fields can be used for components and apps as well as traits for personalization.
Customizations
The field script gives you freedom in the design of the user interface for authors and can even map complex processes within a field. For example, a product selection in Salesforce is a multi-stage process that can be easily mapped.
Integration with apps
Display information and data from Magnolia or peripheral systems within Magnolia and enjoy the benefits of flexibility and customizability. You can provide the editor with the necessary information in the backend to further improve the author experience.
Developer friendly
JS fields can be developed by frontend developers without the need for in-depth knowledge of JAVA. Complex connections to peripheral systems can be simplified here.
Conclusion
JS fields extend Magnolia's already wide range of functions. They bring more possibilities for third-party system integrations paired with developer-friendliness, help to further improve the author experience and thus ultimately also the customer experience.
Use cases are endless and also help reduce integration costs. All in all, another step towards more composability and content orchestration.