The Shop module offers basic e-commerce functionality for Magnolia. The module provides a flexible data structure and a set of classes for handling the data. You define the look and behavior of the shop. The module includes templates and components that adhere to the pop theme. Magnolia partner fastforward started the Shop module and developed the first version in collaboration with Magnolia International Ltd.

Features:

  • Products, prices and shopping carts are managed in apps.
  • Example website structure with shop front, product detail and shopping cart pages/demo-features/modules/sample-shop.
  • Teaser components for promoting products, campaigns and items on sale.
  • Checkout process implemented as a multistep form.
  • Run multiple shops in a single Magnolia instance. Different products, countries and currencies.
  • Each shop can have its own security. Grant editors permission to the shops they work with.

You can view the sample shop in Pages > /demo-features/modules/sample-shop.

This is a community module, maintained by volunteers in the Magnolia developer community. The module is not complete and has open issues. We rely on community members to submit fixes and patches. Your contributions are always welcome. This document describes the module as it should work in an ideal case. If you use the module in a production environment and have a support contract, contact Magnolia Support to get help.
See: Open issues.

Download

The Shop module is not part of the Magnolia bundle. Download the Shop bundle from our Nexus repository and install the following jars:

  • magnolia-module-shop
  • magnolia-module-ocm: saves the shopping cart bean and cart items to JCR nodes, distributes order numbers, and configures what to save.
  • jackrabbit-ocm

Installing

Shop is a Community Edition module. It is typically not installed. 

Unable to render {include} The included page could not be found.

Uninstalling

Unable to render {include} The included page could not be found.

Known limitations

  • Products in a given shop can be priced in only one currency at a time (default price category). To change this behavior, write a custom price category manager.
  • You cannot define different prices for different product options (sizes, colors) of the same product.
  • No payment processing is included.

Module configuration

The Shop module is configured at Configuration > /modules/shop.

Node nameValue

 modules


 shop


 apps


 dialogs


 fieldTypes


 templates


The Magnolia OCM module is used to save the shopping cart bean and cart items to nodes, to distribute order numbers (order number is the name of the cart node), and to configure what to save. It implements the shopping cart functionality and is configured at Configuration > /modules/ocm. Here's the configuration for the of the defaultShoppingCart.

Node nameValue

 modules


 ocm


 pages


 config


 classDescriptors


 defaultShoppingCart


 fieldDescriptors


 beanDescriptors


 collectionDescriptors


 class

org.apache.jackrabbit.ocm.mapper.model.ClassDescriptor 

 className

info.magnolia.module.shop.beans.DefaultShoppingCartImpl 

 jcrType

mgnl:contentNode 

 nextBeanId

176

 parentJcrType

mgnl:folder

 defaultShoppingCartItem


 defaultShoppingCartOption


Apps

All shop related items except product categories are managed in apps. Product categories are created automatically for each page based on the Product Category template

The Manage Shops group contains apps that allow you manage items for all shops in once place. Create new shops in All shops.

When you create a shop, a dedicated app group is created automatically for that shop. This allows you to manage permissions for each shop. Here's the app launcher menu for the Sample Shop.

Workspaces

The module creates four workspaces:

Creating a shop

To create a new shop, go to Manage Shops > All Shops and click Add Shop. The module also ships with a sample shop that you can customize to your liking.

When you save the new shop, Magnolia creates dedicated app group for quick access to the shop.

Parent nodes for the various configuration options are created automatically. You can add as many tax and price categories, currencies, countries and shipping options as necessary by selecting the parent item and adding relevant sub items. The configured options are assigned on a product-by-product basis when adding products.

 

Name and title

Fields:

  • Shop name: Internal name of the shop.
  • Title: Shop title.

Price category and cart

(warning) The default classes and cart session variable are auto filled. Do not change these unless you have a customized implementation.

  • Default Price Category: Price category that renders on pages by default. Return to this field after you have set up your price categories to select the default. You can leave this blank if you only have a single price category.
  • Price Category Manager: DefaultPriceCategoryManagerImpl is the default implementation of the PriceCategoryManager interface and is used get the default price category for a selected shop.
  • Cart Session Variable: Name of the cart session variable.
  • Cart Bean Type: Provide a descriptive name (without spaces).
  • Cart Class: DefaultShoppingCartImpl is the default implementation of the ShoppingCart interface. It is registered in the ocm module configuration (above). The implementation includes order, billing and shipping addresses, and allows only one cart item per product (i.e. when adding the same product multiple times, the quantity of the cart item will be increased).

Tax categories

Value added tax (VAT) is levied at different rates on different products. It is calculated as a percentage of the net price. You can create several tax categories such as normal goods at 7.6%, reduced at 2.4% and so on. Tax is added to the price at checkout. The amount of tax applied to a particular product depends on the price category the product belongs to.

Fields:

  • Tax Category is a unique ID for the category. For example, 001-Books. The ID can contain letters, numbers and special characters with certain exceptions.
  • Title is the name of the tax category that is displayed to editors when they add products, for example Books.
  • Tax is a numerical value of the tax percentage. For example, if a VAT of 7.6% is levied on books, enter 7.6 into this box. The number format is Double where period is a decimal point.

Currencies

The Shop module supports multiple currencies. This is useful for large shops with a global customer base and shops that are located near a two-country border.

(warning) While it is possible to configure multiple currencies, only one currency is used at a time. Customers cannot switch between currencies in the default implementation; all products are priced in the currency defined in the default price category.

Fields:

  • Currency is the unique ID of the currency such as USD, EUR or CHF. It is displayed to editors when they edit product details.
  • Title such as $, or CHF. It is displayed to customers next to the product price in the shop.
  • Formatting convention. Set the format used to display currency so that it matches the currency's locale. Whole numbers are represented with a number sign # and parts with zero 0. For example, U.S. cents are separated from whole dollars with a period and a comma is used as thousands separator, such as in 1,234.56. Formatting for dollars is therefore ###,###.00. The corresponding convention for Swiss Francs is 1'234.55 (###'###.00) and for euros 1.234,56 (###.###,00).

Price categories

Price category defines the currency in which a product is sold and whether tax should be applied.

Fields:

  • Price category is a unique ID for the category such as "standardPrice" or "taxfreeSwissFranc".
  • Title is displayed to editors who set product prices. Make the title descriptive and immediately understandable such Tax-free Swiss franc.
  • Currency. Select a currency. Options in this list are created in Currencies.
  • Tax. Whether the price includes tax or not.

Once your price categories are set up, launch the All shops app and select the default currency in the Systems tab.

DefaultPriceCategoryManagerImpl is the default implementation of the PriceCategoryManager interface and allows to display one price category at a time. To sell the same product in different currencies and tax scenarios, for example, you need to write a custom price category class that allows switching between price categories. Suppose you sell the same product in two different currencies: euros and Swiss francs. Customers who pay euros come from the euro area where your shop is located so they need to pay value-added tax (VAT). Swiss franc customers come from across the border in Switzerland so no tax is levied on their purchases. You need two price categories: Standard selling price and Tax-free Swiss franc. You also need to allow customers to choose the currency in which they wish to pay for products.

Shipping options

You can set up different shipping options for different countries.

(warning) Shipping options are currently not used by the default shopping cart implementation. 

Fields:

  • Key is the unique ID of the shipping option.
  • Title is the title of the shipping option, such as FedEx USA. It is used to link an option to a country.
  • VAT category. Select a tax category. Options in this list are created in Tax categories.
  • Tax. Whether the shipping price includes tax or not.
  • Shipping prices. Shipping costs based on weight. Product weight is entered when adding products.

Countries

Define the countries you ship to.

(warning) Countries are currently not used by the default shopping cart implementation.

Fields:

  • ISO 3166-1 alpha-3 is the standardized ISO 3166-1 county code. 
  • Title is the country title.
  • Liable to VAT: Whether sales to this country are liable to VAT. If not checked all sales to customers of this country will be exempted from VAT
  • Shipping options: Select the shipping options applicable to the country

Suppliers

You can add product suppliers in Manage shops > All suppliers or the dedicated Suppliers app for the shop. Editors select suppliers for each product when adding products. Supplier details are stored in the shopSuppliers workspace. The Supplier, Address and Logo tabs include fields for complete supplier details.

(warning) Supplier content is currently not rendered on the product category and detail pages, but you can customize the components to render it.

Shop pages

The module includes page templates to display a shop on your site. A shop has its own navigation. For this reason, all pages except the shop home and category pages should be hidden from standard navigation in the page properties dialogs. The page templates are configured in Configuration > /modules/shop/templates/pages.

At minimum, a shop requires these pages:

PageTemplateDescription
<shop name>Shop HomeShop home page. When you add a page based on the Shop Home template the system creates a basic shop structure automatically. In the page properties dialog you can select the relevant shop.
  • <product categories>
Product CategoryOne page for each product category.
  • <product detail>
Product DetailA single page. Renders details of all products
  • <product search result>
Shop Search ResultA single page. Renders product search results.
  • <keyword search result>
Shop Keyword Search ResultA single page. Renders keyword search results. Keywords are set when adding products and rendered in the extras tag cloud component.
  • <shopping cart>
Shopping CartAdds a shopping cart.
    • <checkout form>
Checkout FormStep one of the checkout process. Includes a shipping address form.
      • <billing address>
Shop Form StepStep two of the checkout process. Includes a billing address form.
      • <confirm order>
Confirm Order Form StepStep three of the checkout process. Allows user to confirm order and address information.
    • <confirmation>
Confirmation PageConfirms order and provides an order number.

Product categories

Categories organize the products sold in the shop. A book shop might have categories such as Travel, Gardening and Audiobooks. The Travel category might split further into Europe, Latin America and Middle East. The purpose of categories is to help customers browse the shop and find products they are interested in. Each category is a page in the shop site hierarchy. Make sure your category taxonomy is logical. It makes finding products quicker.

Product categories are created automatically for each page based on the Product Category template. The product category page structure determines the navigational structure in the shop. The module automatically creates a list of categories in the Products app for selection when editors add products. Here's the page structure for our T Shirt shop example.

This is what the shop navigation looks like to the visitor:

Keywords

The Shop module uses the Categories app to assign keywords to products. You can select keywords as you add products. The extras tag cloud component that is autogenerated on the Product Category template renders links for all keywords assigned to products within the product category. When clicked, products that have the keyword are displayed.

Adding products

Products are the items sold in the shop: books in a book shop, songs in a music shop and so on.

Add products in the Products app. The Product Detail template renders products on pages. You can organize products into folders to match your categories or any other suitable structure, for example by supplier. The structure has no bearing on functionality. 

The Product dialog contains all the necessary fields for your products. All shop configuration options such as price categories, shipping options and countries, and suppliers can be linked to individual products.

Product details:

  • Product is a unique ID for the product. In a book shop it could be the ISBN number of the book such as 978-1613820773 for A Tale of Two Cities by Charles Dickens. The ID can also match a product ID in an external warehousing system if you import products into Magnolia. Use IDs that make sense for your products. The ID is not displayed to customers in the shop by default.
  • Title is the product name displayed to customers. Use titles that customers would expect to find when searching for products.
  • Description (short) is a brief description of the product. It is displayed in product teasers, list components and search results.
  • Description (full) continues the short description. Don't repeat the text of the short description in the full description! The full description is appended immediately after the short description on the product detail page. If you repeat the text, it will be repeated in the shop.
  • Image. Select an image from the DAM. The product image displays in teasers, lists and product detail components in the shop.

Categories and keywords:

  • Product categories: Check the category/ies the product belongs to. Categories come from the category pages under the shop home page. For example, if you categorize a book such as A Guide to the Gardens of Kyoto as both Gardening and Travel, it will be displayed to customers on both category pages. Another example is a book that includes a CD. It could be categorized as a book and an audiobook.
  • Additional Keywords: Add as many keywords as necessary. They help users find related content.

Pricing:

  • Price: Enter the product price
  • Tax category: Apply a tax category.

Weight and size:

  • The fields include typical metrics required to calculate shipping costs.

The product looks like this on the category page:

And like this on the detail page:


(warning) You can also edit products directly on Web pages in the page editor. Click the Edit Product link on a category page to open the dialog in the Products app. 

Product options

Product options are variations within one product such as sizes or colors. For example, if you sell the same shirt in different sizes and colors create variants such as S, M, L, XL, red, white, yellow etc. Different options can be created for each product.

The options are displayed in dropdowns on the product category and detail pages.

Shopping cart

The Shopping Cart component is autogenerated in the extras area on product category and detail pages. The component allows users to add products to the cart. You can make the component available on any template.

The View Shopping Cart link opens the Shopping Cart page that is based on the Shopping Cart template. Prices of all units are totaled and VAT is added if applicable. In the cart the customer can add and remove units of a product using the plus ( + ), minus ( - ) and delete buttons.

Checkout

Checkout is a three-step form that asks the customer to provide a shipping address, billing address and confirmation. Once the order is successfully submitted, the customer is given an order number.

  • Checkout Form
  • Shop Form Step
  • Confirm Order
  • Confirmation

You can configure the form on the shipping address page (Checkout Form template) to send emails to the user and a shop administrator. Here's a Freemarker example you can use to render product and cart details in the confirmation email. See Form module and Form component for more.

Thank you for your order:
Your order number is: ${cartId}
[#list cart.getCartItems() as product]           
Product Name: ${product.productTitle}
            Quantity: ${product.quantity}
            Unit Price: ${product.unitPrice?string("0.00")}
            Total: ${product.itemTotal?string("0.00")}
[/#list]
Subtotal: ${cart.grossTotalExclTax?string("0.00")}
Vat: ${cart.itemTaxTotal?string("0.00")}
Total: ${cart.grossTotalInclTax?string("0.00")}

Shopping carts app

Full details of the order are stored in the Shopping Carts app. The order number matches the shopping cart node name.

The default SaveAndConfirmFormProcessor class converts the order JavaBean object to nodes and properties using Jackrabbit's Object Content Manager (OCM) framework. This functionality is provided by the Magnolia OCM module which is required. You can export the order to a third party warehouse or ERP system by writing a custom shopping cart processor.

Teasing products

Use the Shop Product Teaser component to showcase products. The component is available in main area on the shop home page and in extras area on other appropriate shop templates. The purpose of a teaser is to promote the product and invite the customer to find out more.

STK Availabiltiy

The shop module functionality is available in the STK. It is a good example of how to extend the STK to provide additional functionality.

Template availability

Templates are made available in STK > Site Definitions /default/templates/availability/templates.

Node nameValue

 default


 templates


 prototype


 availability


 templates


 stkHome


 ...


 shopHome


 id

shop:pages/shopHome

 shopProductCategory


 ...


Page templates

Page templates are configured at Configuration > /modules/shop/templates/pages. They are STK templates and define only modifications to the template prototype.

Here's the template definition of the shopProductCategory template.

Node nameValue
 modules

 shop


 templates


 pages


 shopProductCategory


 navigation


 areas


 bodyID

shop

 category

feature

 class

info.magnolia.module.templatingkit.templates.pages.STKPage 

 dialog

standard-templating-kit:pages/section/stkSectionProperties

 i18nBasename

info.magnolia.module.shop.messages

 modelClass

info.magnolia.module.shop.templates.ShopSingletonParagraphTemplateModel

 renderType

stk

 subcategory

product-category

 title

templates.shopProductCategory.title

 visible

 true

Shop home template

The shop home template is essentially a section template.

Properties:

  • bodyID: section.
  • dialog: shop:pages/shopSectionProperties (see below).
  • modelClass: ShopHomeParagraphTemplateModel that extends STKPageModel to generate the basic shop page structure automatically. The structure includes one product category, product detail, product search result, keyword search result and checkout form pages. Here's the code snippet that achieves this.
createShopPage(content, "sample-category", "shop:pages/shopProductCategory");
createShopPage(content, "product-detail", "shop:pages/shopProductDetail");
createShopPage(content, "product-search-result", "shop:pages/shopProductSearchResult");
createShopPage(content, "keyword-search-result", "shop:pages/shopProductKeywordResult");

Node shoppingCart = createShopPage(content, "shopping-cart", "shop:pages/shopShoppingCart");
Node checkout = createShopPage(shoppingCart, "check-out", "shop:pages/shopCheckoutForm");
createShopPage(shoppingCart, "confirmation", "shop:pages/shopConfirmationPage");
createShopPage(checkout, "form-step", "shop:pages/shopFormStep");
createShopPage(checkout, "confirm-order", "shop:pages/shopFormStepConfirmOrder");

The shopSectionProperties dialog is configured at Configuration > /modules/shop/dialogs/shopSectionProperties. The configuration adds a Shop tab to the standard properties dialog that allows for the selection on the appropriate shop.

Autogeneration

The page templates (except shopHome) use the autogeneration feature in the same way as STK feature templates. Functionality is provided by components that are autogenerated on the page template. Here's the configuration for content area in the shopShoppingCart template.

Node nameValue

 shopShoppingCart


 areas


 intro


 main


 areas


 content


 autogeneration


 content


 singleton


 nodeType

mgnl:component

 templateId

shop:components/features/shopShoppingCart 

 generatorClass

info.magnolia.rendering.generator.CopyGenerator

 enabled

true

 type

single

Component templates

Component templates are configured at Configuration > /modules/shop/templates/components.

Features

The names of the feature component definitions correspond with the names of the templates they are used on, for example the shopShoppingCart template autogenerates the shopShoppingCart component in content area. Here's the definition of the shopProductDetail component.

Node nameValue
 components

 features


 shopProductDetail


 parameters


 divClass

teaser

 divIDPrefix


 headingLevel

 h2

 description

-

 dialog

shop:shopProductList

 i18nBasename

info.magnolia.module.shop.messages

 modelClass

info.magnolia.module.shop.paragraphs.ShopParagraphModel 

 renderType

stk

 templateScript

/shop/paragraphs/features/productDetails.ftl

 title

paragraphs.features.shopProductDetail.title

Form

The shopForm component, autogenerated on the shopCheckoutForm template, is a standard Magnolia multistep form customized for shop functionality. See the /demo-features/modules/sample-shop/shopping-cart page for the default form settings and email code. (warning) Configure valid SMTP settings to test the form.

  • formProcessors: There are three custom form processors that are not enabled by default:
  • modelClassShopFormModel ensures that the ShopStartStepFormEngine is in use. The engine checks the shopping cart for a form token. This allows users to continue browsing without losing checkout out form data.
Node nameValue
 components

 features


 shopForm


 formProcessors


 saveAndConfirmOrder


 class

info.magnolia.module.shop.processors.SaveAndConfirmFormProcessor

 enabled

true

 sendContactEmail


 class

info.magnolia.module.shop.processors.SendShopOrderEmailProcessor

 enabled

true

 sendConfirmationEmail


 class

info.magnolia.module.shop.processors.SendShopConfirmationEmailProcessor

 enabled


 trackMail

true

 parameters


 areas


 fieldSets


 availableComponents


 formGroupFields


 id

form:components/formGroupFields

 enabled

true

 templateScript

 /form/generic/listArea.ftl

 type

 list

 class

info.magnolia.module.form.templates.components.FormParagraph

 description

form description

 dialog

form:form

 i18nBasename

info.magnolia.module.shop.messages

 modelClass

info.magnolia.module.shop.paragraphs.ShopFormModel

 renderType

freemarker

 templateScript

/shop/paragraphs/features/shopForm.ftl

 title

Form

Here's the shopForm.ftl script that renders the component

[#assign shoppingCart = model.getShoppingCart()]

[#if (!shoppingCart?has_content || shoppingCart.getCartItemsCount() == 0) &amp;&amp; !cmsfn.isEditMode() ]
    <p>${i18n['shoppingcart.empty']}</p>
[#else]
    [#include "/form/components/form.ftl"]
[/#if]

Teasers and extras

The module includes four custom teaser components.

  • shopExtrasProduct and shopProductTeaser are demonstrated above in Teasing products.
  • The other extras components are either available for selection or autogenerated on templates where extras area is enabled.
    • shopExtrasCart adds the shopping cart.
    • shopExtrasTagCloud renders a list of keywords and product count.
    • shopExtrasProductSearch allows a user to search for products.
Node nameValue
 components

 extras


 shopExtrasProduct


 shopExtrasCart


 shopExtrasTagCloud


 shopExtrasProductSearch


 teasers


 shopProductTeaser


Themes

The module adds CSS styles and theme images to the default pop theme in the STK.

The shop.css sheet is referenced In STK > Themes /pop/cssFiles/shop.

Node nameValue

 pop


 cssFiles


 styles


 shop


 farFutureCaching

true

 link

/resources/templating-kit/themes/pop/css/shop.css

 media

 screen, projection

 ie6


You can access the resources in STK > Resources at /templating-kit/themes/pop/css/shop.css and /images/shop

Security

Base role

The module installs the shop-user-base role and grants the superuser role full access to all shop workspaces. The shop-user-base role is not assigned to any user by default. The role allows a user to view content in the Setup, Products and Shopping carts apps, and in the components on pages.

Access control lists:

WorkspacePermissionScopePath
ShopsRead onlySelected and sub nodes/
ShopProductsRead onlySelected and sub nodes/
ShoppingCartsRead onlySelected and sub nodes/

Public users

Public users need write permission to the shoppingCarts workspace and read permission to the other workspaces. To allow public users to view the content of the shop pages and use the cart, create a new role on the public instance with the following permissions and assign it to the anonymous user in Security > Public Users.

Access control lists:

WorkspacePermissionScopePath
ShopsRead onlySelected and sub nodes/
ShopProductsRead onlySelected and sub nodes/
ShopCartsRead/WriteSelected and sub nodes/

Administrators

If you assign the shop-user-base role to editors they can add and edit shop teaser components. To grant permissions to add and edit products in the Products app, and work in the Shopping carts, Shop suppliers and Systems apps, create and assign a new role with one or more of the following permissions.

Access control lists:

WorkspacePermissionScopePath
ShopsRead/WriteSelected and sub nodes/
ShopProductsRead/WriteSelected and sub nodes/
ShoppingCartsRead/WriteSelected and sub nodes/
ShoppingSuppliersRead/WriteSelected and sub nodes/

(warning) These permissions allow the user access the general and dedicated shop apps but you can limit this by configuration.

App access

You can control access to apps in the app and app launcher configurations. See App permissions for more information.

The following example configuration at Configuration/modules/ui-admincentral/config/appLauncherLayout/sampleShop limits access to the Sample shop menu in the app launcher to users assigned the superuser and sample-shop-administrator role.

Node nameValue
 modules

 ui-admincentral


 config


 appLauncherLayout


 groups


 edit


 sampleShop


 apps


 permissions


 roles


 superuser

superuser

 administrator

 sample-shop-administrator

The following example configuration at Configuration/modules/shop/apps/shops limits access to the Manage shops > All shops app to users assigned the superuser role.

Node nameValue
 modules

 shop


 apps


 shop


 shops


 subapps


 permissions


 roles


 superuser

superuser

Payment gateways

The Shop module does not have payment processing. Connection to a payment gateway is a customization task for the implementer. It can be achieved by:

  • Sending client details and total amount to a page on the gateway site. Drawback of this approach is that the user will see that he is redirected to another site.
  • Creating a form processor that talks to the selected payment gateway API.

External product management applications

The easiest way to connect to an external product repository is to import the data into the All products or dedicated products app adhering to the data structure the Shop module uses to store products. This requires a custom import handler. The import mechanism can be scheduled so the data will be automatically updated.

#trackbackRdf ($trackbackUtils.getContentIdentifier($page) $page.title $trackbackUtils.getPingUrl($page))