10 Magento 2 eCommerce Themes: Best Selection of 2018
Magento® is one of the hottest eCommerce platforms on the market, and it’s easy to see why. Magento has a dedicated community of developers and a wide range of easily accessible documentation. Add to that a host of features like pre-coded templates, payment platforms, and themes to fit every online store, and it’s no wonder that Magento has gained popularity so quickly.
But there’s a downside to having many options. How do you know which one is right for your shop? So, to cut through the confusion here’s a breakdown of the top 10 Magento 2 themes. We’ll explore the features and pricing of each, plus service and which is most suitable for different kinds of online store.
What Is the Magento 2 Theme?
Essentially, a theme is an online storefront. It’s the layout of the page, how the menus are arranged, the color scheme, and the general aesthetic presentation. This may seem small, but developers know that the theme can make all the difference when it comes to bounce rates, conversion rates, and overall site success.
For example, you want a professional theme and one that reflects your product or service. Different colors and layouts are suitable for different business. A site that selling tech products will want a clean layout with colors that make your products stand out, while a fashion site needs to have a bit more flash to engage the customers.
Finally, the best themes work well with SEO and are technologically advanced, fitting for all mobile devices and browsers. This means that you’ll be looking for Magento 2 responsive themes capable of adjusting layouts to fit different screen sizes. The good news is that Magento offers themes suitable for all business needs. Let’s have a look at those that top the market for 2018.
Useful for you:
Top Magento 2 Themes 2018
Here is a brief review of the best themes on the market this year. We highlight key features, pricing, service, and the niche they work best for. To explore any theme more fully, simply click the link in the heading.
Ultimo Responsive Magento Theme
Some Key Features of Ultimo:
- Multi-Store Ready
- Responsive, Customizable Layout
- Unlimited Colors and Custom Subthemes
- High-Quality Brand Logos
- More than 50 Content Placeholders
- 12-Column Fluid Grid System
Ultimo is available for $99. This includes future updates, quality control checking by Envato, and 6 months of Infortis support. An additional $31.50 will extend the support to 12 months.
Fastest Multipurpose Responsive Theme
This theme is aptly named – it was designed to be the fastest-loading theme on the market. It also provides a wide range of customizable options, making it suitable for any type of business. Fastest is loaded with extra features that come free with the package. From social sharing to brand tools, it provides everything you need to tailor the site to your product.
Some Key Features of Fastest:
- Brand pages featuring SEO optimization, layer navigation, and social networking
- Brand search boxes and brand list widgets
- Brand logos, banners, and descriptions
- Custom Ajax carts
- Simple blog extensions
- Pop-up newsletters and promo panels
Fastest can be purchased for $99. The package comes with free features like Ajax Layered Navigation and the Codazon slideshow extension. It also comes with 6 months free support from Codazon, quality control from Envato, and future updates. An additional six months of support can be purchased for $31.50.
Unero Minimalist Magento 2 and 1 Theme
Unero is designed to eliminate the non-essentials so that the products will stand out. This makes it suitable for a wide range of different businesses, including decoration, furniture, fashion, and more. It also has features which support an omnichannel approach, allowing customers to locate physical shops or buy directly from the site. Its streamlined layout makes site navigation easy, boosting customer engagement and increasing conversion rates.
Some Key Features of Unero:
- MGS Frontend Builder
- Simple blog extensions
- 360-degree image view
- Advanced Reports
- Ajax Fly Cart
- Social login
Like Ultimo and Fastest, the Unero theme costs only $99 and comes with Envato quality checking, 6months of free service (through ArrowHiTech), and future updates. Also like the themes above, service can be extended to 12 months for only $31.50.
Bencher Responsive Magento 1 & 2 Theme
Some Key Features of Bencher:
- Custom social media integration
- Top Menu and Extra Menu
- Custom Hover for product image
- Untimated Colors Power Admin
- Ajax cart
- Simple Blog Extensions
Bencher is one of the least expensive themes in this list, able to be purchased for only $84. This package also includes future update, Envato quality checking, and six months of support through Alotheme. This support can be extended to twelve months with a payment of $25.88.
Hermes Premium Responsive Magento 2 & 1 Theme

The adaptable, intuitive design of Hermes Magento theme makes it simple to customize. It includes six basic designs which can then be adjusted as needed to suit your store. This makes it yet another theme that works well with any type of business. It also means that your theme can be tailored with a minimum of time and effort. Hermes also has Lazy Loading so that it responds quickly and with a minimum of lag time.
Some Key Features of Hermes:
- New Products Slider Extension
- Smart Megamenu
- Moo-Cloudzoom Product Image Zoom Extension
- Categories Product Extension
- Flexible styling, fonts, and colors
- Ajax Layered Navigation
Hermes is the least expensive theme on this list, able to be purchased for only $55. The basic package includes six months of service by The_Blue_Sky, future updates, and Envato quality checking. The support can be extended to twelve months with no more than $15.
HippoSpa – SPA Store Magento Theme
Some Key Features of HippoSpa:
- Free assistance 24/7
- SEO and Performance optimization
- Cross-browser compatibility
- Newsletter Pop-up
- MegaMenu
- Featured Products Theme Options
HippoSpa can be purchased for $179. Support is free, but other services will have to be bought individually. These include installation, which costs $49 and hosting, which costs $27. Additional options include the SEO boost for $99 and the 1-year SSL certificate for $10.
Pearl Responsive Theme
Some Key Features of Pearl:
- Plenty of frontend admin control options
- Unlimited color options and Google fonts
- Ajax Cart and Quick View
- Flexible Header and Footer Options
- Flexible Product Page Design
- Google Analytics Advanced eCommerce Tag Manager
Pearl can be purchased for $499 and comes with three months of free service.
iShop Electronic Magento 2 Theme
If you’re looking for a theme designed to support electronic and technological products, iShop is the perfect solution. It offers a clean layout and intuitive navigation, with features that showcase your products without crowding the page. iShop also offers full responsiveness, high performance, and extreme customizability. Its professional design helps to boost traffic and conversion rates for any online electronic store.
Some Key Features of iShop:
- MegaMenu
- Flexible Architecture
- Cross-browser Compatibility
- Social Options
- Newsletter Pop-up
- Google Web Fonts
- Carousel Product Listing and Configurable Swatches
The iShop theme costs $179 and comes with free 24/7 access to a pro support team. Installation runs an additional $49, and hosting is provided for $27. Optional services like SSL certificates and SEO boosts can be purchased along with the theme for additional fees.
Magetique – AMP-Ready Magento 2 Theme
Some Key Features of Magetique:
- Intuitive Interface
- Parallax and Video Background
- Cross-browser Compatibility
- MegaMenu
- Social Options
- Advanced Theme Options
Magetique can be purchased for $179 and offers 24/7 free support. Installation and hosting are extra: $27 for hosting and $49 for installation. A 1-year SSL certificate can be purchased for $10 dollars, and SEO optimization will cost an additional $99.
Recuidi Healthy Food Store Magento Theme
The prime theme of 2018 for online healthy food stores is Recuidi. It offers a wide selection of theme options that are perfectly suited to showcase food with gorgeous colors and aesthetic presentation. Recuidi uses many banners and live-search functionality, making it easy for customers to find products, recipes, and other offerings quickly and with minimum effort. If you’re ready to set up an online organic food store or expand your physical store with online options, Recuidi offers a simple and professional solution.
Some Key Features of Recuidi:
- MegaMenu
- Newsletter Pop-up
- Products Filter
- Social Options
- Features Products
- Parallax and Video Background
Recuidi can be purchased for $179 and comes with free 24/7 service. Just as with iShop and Magetique, installation for Recuidi costs $49 and hosting can be bought for $27. Also as with the other themes, SEO and other options can be purchased for an additional charge.
Must-Have Magento Extensions to Spike Your Sales
If you own an eCommerce store you’ve probably used or have thought of using Magento® 2. This platform is known for its various benefits; including, the generation of sales and increased conversions. Today we will share top Magento extensions to increase your sales results.
What is Magento Extension?
Magento extensions are tools that allow you to enhance your Magento store. You can customize the site by installing extensions from the Magento extension store.
Magento Marketing Extensions
Among its many extensions, Magento offers marketing features that allow merchants to expand their marketing techniques, reach, etc. The method in which they do this depends entirely on the extension that’s being used. Below, you will find top extensions to increase the results from your marketing efforts.
Loyalty Program by Amasty
This extension is available with both the Community and the Enterprise editions. By using this marketing tool, merchants are able to create loyalty programs for their customers and clients. They can create rewards for those who receive points or who shop often.
A major benefit of using this extension is that merchants can choose among several promotional offers and it includes16 discount codes.
Coupon Link by Web Solutions NYC
By using Coupon Link, merchants are able to create links that are associated with coupon codes. When customers use these links, it provides them with a discount or coupon.
The way it works will depend on how you want to run your store. Most often, the URL is used in blog posts and marketing schemes.
MailBot by Beeketing
MailBot allows merchants to create pre-made campaigns. These include anything from scheduling emails or picking products to display. This is a benefit for anyone who is stressed on time because you can prepare all of your emails in advance to ensure the exact time of your email marketing campaign.
Gift Card by Aheadwords
This extension allows merchants to create gift cards for their customers and clients. The cards are customizable with this extension and the merchants can specify the values of the cards.
Clients and customers are able to use these cards to specify their own gift vouchers based on what their individual preferences are.
Subscribe at Checkout by Mageside
One of the most important factors in marketing is ensuring that your customers are subscribed to your newsletters. That’s because, after the initial sale, you can send them emails that will remind them you’re still around and that you have products that could be interesting for them.
With this extension, you can force your customers to subscribe by email before they checkout.
Rich Snippets by Atwix
The Rich Snippets extension allows you to show more detailed results. When your customers search for your products they’ll see more details about your every item.
Studies show that when eCommerce sites use Rich Snippets, their results tend to show up in higher positions. These results show up 20% to 30% more in increasing their ranking positions.
Even if you make everything to attract your customers with offers and provide them with your product updates, if you have some issues with navigation at your site, they will force difficulties when browsing around. That is why we suggest you the best extensions to improve the user experience at your store.
Best Free and Paid Magento 2 Extensions for Usability
If you’re looking for Magento eCommerce extensions to increase your store’s reach and usability, you might be wondering if there are any you can get without having to pay anything at all. That’s what we’re going to discuss in this section!
Improved Layered Navigation by Amasty
This Magento Commerce extension is one that many install in their Magento eCommerce store(s) because it allows customers to browse through your product catalog more comfortably.
The major benefit of using eCommerce extensions is that your customers have more access to your products. When they have this access to your products, they have the opportunity to buy them more easily.
Beyond this, you can also create the menu to suit your needs, as well as the needs of your clients. The SEO feature of this extension allows you to increase your ranking on Google because you can tailor your URLs and page names to include keywords.
AJAX Cart Pro for Magento 2 by Aheadwords
The AJAX Cart Pro for Magento 2 extension is one of the Magento ?ommunity extensions that allows merchants to create an “Add to cart” feature that immediately adds products from your website to their carts. These products can also have reviews and small descriptions added to them with this feature.
Request for Quote by FME
This is the perfect extension for anyone who wants to offer quotes to their clients. You can install fields for your customers or clients to fill out their personal information. Once they’ve done this, they have the opportunity to send the information to you in order to get an accurate quote or cost of the product.
Share Buttons by Neklo
Any merchant knows the importance of expanding their reach on social media. If you have Instagram, Twitter, Facebook, or Youtube pages, this widget tool allows you to share your site with your other websites. The Share Buttons extension also serves as a Magento blog extension.
Your customers can share your site to their own pages. This is the digital equivalent of word-to-mouth; only, hundreds of people can be exposed to your site at a time.
Detailed Product Review by MageWorkshop
When customers have a good or bad experience with your store, they might want to leave a detailed review about it. This allows potential customers who are using a Magento search module to get an idea about your products.
Development of Extensions
Now that you know about the various extensions available for Magento eCommerce business owners, you might be wondering about how extensions can influence the development of your site and how you can develop extensions on your site.
How to Install Plugin in Magento?
Installing a Magento plugin can be challenging; however, it is very manageable for all merchants when they use the following steps.
First, you should download or purchase the plugin you’re looking for. If a ZIP file is downloaded, you’ll have to unzip it. Some computers come with programs that automatically unzip folders when you try to open them.
Next, you’ll have to disable the Cache. Run the command and your extension will be installed from that moment. For the full guide, you can refer to our How to section.
How to Make Extension in Magento?
If you want to make your own extension in Magento, you’ll have to start out by disabling your Magento cache. Next, you’ll have to put Magento into developer mode by going to Magento 2 root in your terminal.
From here, you’ll have to create a Hello World module folder. You’ll also have to create a file called etc/module.xml, enable the module, and create a controller. This will give you an ability to create custom modules.
Managing the Magento 2.2.4 Category Tree Checkbox Bug
When using Magento® 2.2.4, a bug was identified in the category tree on the page for editing pricing rules. When trying to create pricing rules by product category (for a catalog or cart) not every category appeared in the category tree (a component of the form for generating a pricing rule for a category). More precisely, the root category of the first store, the first category of the store, and all of its child categories were displayed. Other categories were not displayed in the tree.
To fix this problem, we must analyze the implementation of the component, which you can see in the sample code in the next section.
Analysis of the Component for Price Rule by Product Category
Like the majority of Magento 2 components, this component has a back end and front end part (Javascript). A problem like this could be caused either by the fact that not all categories were transferred from the backend or by the fact that some categories weren’t rendered by the component in the Javascript tree for some reason. The component is implemented by the Magento\Catalog\Block\Adminhtml\Category\Checkboxes\Tree block. This block’s template, Magento_Catalog: catalog/category/checkboxes/tree.phtml, is set in its methods, and in it, the component is initialized by data in JSON format. The template looks like this in Magento 2.2.4:
<?php $_divId = 'tree-div_' . time() ?>
<div id="<?= /* @escapeNotVerified */ $_divId ?>" class="tree"></div>
<script id="ie-deferred-loader" defer="defer" src="//:"></script>
<script>
require(["Magento_Catalog/js/category-checkbox-tree"], function (element) {
element({
"dataUrl": "<?= /* @escapeNotVerified */ $block->getLoadTreeUrl() ?>" ,
"divId": "<?= /* @escapeNotVerified */$_divId ?>",
"rootVisible": <?php if ($block->getRoot()->getIsVisible()): ?>true<?php else : ?>false<?php endif; ?>,
"useAjax": <?= /* @escapeNotVerified */ $block->getUseAjax() ?>,
"currentNodeId": <?= (int)$block->getCategoryId() ?>,
"jsFormObject": <?= /* @escapeNotVerified */ $block->getJsFormObject() ?>,
"name": "<?= /* @escapeNotVerified */ htmlentities($block->getRoot()->getName()) ?>",
"checked": "<?= /* @escapeNotVerified */ $block->getRoot()->getChecked() ?>",
"allowDrop": <?php if ($block->getRoot()->getIsVisible()): ?>true<?php else : ?>false<?php endif; ?>,
"rootId": <?= (int)$block->getRoot()->getId() ?>,
"expanded": <?= (int)$block->getIsWasExpanded() ?>,
"categoryId": <?= (int)$block->getCategoryId() ?>,
"treeJson": <?= /* @escapeNotVerified */ $block->getTreeJson() ?>
});
})
</s
As you can see, the Javascript component is implemented in a separate JS file: Magento_Catalog/js/category-checkbox-tree. This is an important difference from all previous versions since previously the Javascript of this component was implemented in the template, not put to a separate file. The code of this Javascript component is as follows:
define([
'jquery',
'prototype',
'extjs/ext-tree-checkbox',
'mage/adminhtml/form'
], function (jQuery) {
'use strict';
return function (config) {
var tree,
options = {
dataUrl: config.dataUrl,
divId: config.divId,
rootVisible: config.rootVisible,
useAjax: config.useAjax,
currentNodeId: config.currentNodeId,
jsFormObject: config.jsFormObject,
name: config.name,
checked: config.checked,
allowDrop: config.allowDrop,
rootId: config.rootId,
expanded: config.expanded,
categoryId: config.categoryId,
treeJson: config.treeJson
},
data = {},
parameters = {},
root = {},
len = 0,
key = '',
i = 0;
/* eslint-disable */
/**
* Fix ext compatibility with prototype 1.6
*/
Ext.lib.Event.getTarget = function (e) {// eslint-disable-line no-undef
var ee = e.browserEvent || e;
return ee.target ? Event.element(ee) : null;
};
/**
* @param {Object} el
* @param {Object} config
*/
Ext.tree.TreePanel.Enhanced = function (el, config) {// eslint-disable-line no-undef
Ext.tree.TreePanel.Enhanced.superclass.constructor.call(this, el, config);// eslint-disable-line no-undef
};
Ext.extend(Ext.tree.TreePanel.Enhanced, Ext.tree.TreePanel, {// eslint-disable-line no-undef
/* eslint-enable */
/**
* @param {Object} config
* @param {Boolean} firstLoad
*/
loadTree: function (config, firstLoad) {// eslint-disable-line no-shadow
parameters = config.parameters,
data = config.data,
root = new Ext.tree.TreeNode(parameters);// eslint-disable-line no-undef
if (typeof parameters.rootVisible != 'undefined') {
this.rootVisible = parameters.rootVisible * 1;
}
this.nodeHash = {};
this.setRootNode(root);
if (firstLoad) {
this.addListener('click', this.categoryClick.createDelegate(this));
}
this.loader.buildCategoryTree(root, data);
this.el.dom.innerHTML = '';
// render the tree
this.render();
},
/**
* @param {Object} node
*/
categoryClick: function (node) {
node.getUI().check(!node.getUI().checked());
}
});
jQuery(function () {
var categoryLoader = new Ext.tree.TreeLoader({// eslint-disable-line no-undef
dataUrl: config.dataUrl
});
/**
* @param {Object} response
* @param {Object} parent
* @param {Function} callback
*/
categoryLoader.processResponse = function (response, parent, callback) {
config = JSON.parse(response.responseText);
this.buildCategoryTree(parent, config);
if (typeof callback === 'function') {
callback(this, parent);
}
};
/**
* @param {Object} config
* @returns {Object}
*/
categoryLoader.createNode = function (config) {// eslint-disable-line no-shadow
var node;
config.uiProvider = Ext.tree.CheckboxNodeUI;// eslint-disable-line no-undef
if (config.children && !config.children.length) {
delete config.children;
node = new Ext.tree.AsyncTreeNode(config);// eslint-disable-line no-undef
} else {
node = new Ext.tree.TreeNode(config);// eslint-disable-line no-undef
}
return node;
};
/**
* @param {Object} parent
* @param {Object} config
* @param {Integer} i
*/
categoryLoader.processCategoryTree = function (parent, config, i) {// eslint-disable-line no-shadow
var node,
_node = {};
config[i].uiProvider = Ext.tree.CheckboxNodeUI;// eslint-disable-line no-undef
_node = Object.clone(config[i]);
if (_node.children && !_node.children.length) {
delete _node.children;
node = new Ext.tree.AsyncTreeNode(_node);// eslint-disable-line no-undef
} else {
node = new Ext.tree.TreeNode(config[i]);// eslint-disable-line no-undef
}
parent.appendChild(node);
node.loader = node.getOwnerTree().loader;
if (_node.children) {
categoryLoader.buildCategoryTree(node, _node.children);
}
};
/**
* @param {Object} parent
* @param {Object} config
* @returns {void}
*/
categoryLoader.buildCategoryTree = function (parent, config) {// eslint-disable-line no-shadow
if (!config) {
return null;
}
if (parent && config && config.length) {
for (i = 0; i < config.length; i ) {
categoryLoader.processCategoryTree(parent, config, i);
}
}
};
/**
*
* @param {Object} hash
* @param {Object} node
* @returns {Object}
*/
categoryLoader.buildHashChildren = function (hash, node) {// eslint-disable-line no-shadow
// eslint-disable-next-line no-extra-parens
if ((node.childNodes.length > 0) || (node.loaded === false && node.loading === false)) {
hash.children = [];
for (i = 0, len = node.childNodes.length; i < len; i ) {
/* eslint-disable */
if (!hash.children) {
hash.children = [];
}
/* eslint-enable */
hash.children.push(this.buildHash(node.childNodes[i]));
}
}
return hash;
};
/**
* @param {Object} node
* @returns {Object}
*/
categoryLoader.buildHash = function (node) {
var hash = {};
hash = this.toArray(node.attributes);
return categoryLoader.buildHashChildren(hash, node);
};
/**
* @param {Object} attributes
* @returns {Object}
*/
categoryLoader.toArray = function (attributes) {
data = {};
for (key in attributes) {
if (attributes[key]) {
data[key] = attributes[key];
}
}
return data;
};
categoryLoader.on('beforeload', function (treeLoader, node) {
treeLoader.baseParams.id = node.attributes.id;
});
/* eslint-disable */
categoryLoader.on('load', function () {
varienWindowOnload();
});
tree = new Ext.tree.TreePanel.Enhanced(options.divId, {
animate: false,
loader: categoryLoader,
enableDD: false,
containerScroll: true,
selModel: new Ext.tree.CheckNodeMultiSelectionModel(),
rootVisible: options.rootVisible,
useAjax: options.useAjax,
currentNodeId: options.currentNodeId,
addNodeTo: false,
rootUIProvider: Ext.tree.CheckboxNodeUI
});
tree.on('check', function (node) {
options.jsFormObject.updateElement.value = this.getChecked().join(', ');
varienElementMethods.setHasChanges(node.getUI().checkbox);
}, tree);
// set the root node
//jscs:disable requireCamelCaseOrUpperCaseIdentifiers
parameters = {
text: options.name,
draggable: false,
checked: options.checked,
uiProvider: Ext.tree.CheckboxNodeUI,
allowDrop: options.allowDrop,
id: options.rootId,
expanded: options.expanded,
category_id: options.categoryId
};
//jscs:enable requireCamelCaseOrUpperCaseIdentifiers
tree.loadTree({
parameters: parameters, data: options.treeJson
}, true);
/* eslint-enable */
});
};
});
As you can see, this component is a Javascript function that initializes an object (the category tree) and also auxiliary objects, which allow to display a category tree with checkboxes in the browser. The libraries jQuery, prototype, and extjs are used to do this. The last two of these have been used since Magento 1.
Using the Javascript browser debugger, I was able to establish that the category tree from the back end is completely transferred and the problem with rendering occurs at the Javascript component level. The location of the error was established, after detailed analysis, to be the buildCategoryTree method of the categoryLoader object. In the component, it looks as follows:
categoryLoader.buildCategoryTree = function (parent, config) {// eslint-disable-line no-shadow
if (!config) {
return null;
}
if (parent && config && config.length) {
for (i = 0; i < config.length; i ) {
categoryLoader.processCategoryTree(parent, config, i);
}
}
};
The problem was in the loop counter variable i. The developers of the last version of the Magento_Catalog module made the variable global within the whole component. As a result, after rendering all of the first category’s child categories, of which there were 42, the cycle was complete. This is because there were far fewer subcategories in the root category, and they were not rendered. The variable should have been made locally in the buildCategoryTree method. It then would have been visible in the processCategoryTree method as well, since it would have been passed as a parameter. In fact, in the component’s implementation in previous versions, this variable was local, which you can see below (in an example from Magento 2.2.3):
categoryLoader.buildCategoryTree = function(parent, config)
{
if (!config) return null;
if (parent && config && config.length){
for (var i = 0; i < config.length; i ) {
config[i].uiProvider = Ext.tree.CheckboxNodeUI;
var node;
var _node = Object.clone(config[i]);
if (_node.children && !_node.children.length) {
delete(_node.children);
node = new Ext.tree.AsyncTreeNode(_node);
} else {
node = new Ext.tree.TreeNode(config[i]);
}
parent.appendChild(node);
node.loader = node.getOwnerTree().loader;
if (_node.children) {
this.buildCategoryTree(node, _node.children);
}
}
}
};
The reason for this bug was established, but another problem arose while attempting to fix it. All of the component’s objects exist only in local variables within the component’s functions and are not visible externally. Passing them into the component of some object that can call external code within the component is also not possible because the component doesn’t call external callback functions and doesn’t throw events. A mixin can’t be created because the component is a Javascript function and doesn’t have methods or properties available from outside.
Ultimately, we decided to completely rewrite the component, although that only required changing one line. This is better than editing the component in the core module. You must replace the template that initializes the component, and you must replace the existing component call in the template with the correct one.
Changes to the Component Code for Fixing the Category Display Problem
Since we’re dealing with a block of the admin panel, the adminhtml_block_html_before event handler can be used, which almost all admin panel blocks call before output. We implement this:
<event name="adminhtml_block_html_before">
<observer name="default_product" instance="Web4pro\Defaultproduct\Observer\Changetemplate" shared="false" />
</event>
class Changetemplate implements \Magento\Framework\Event\ObserverInterface {
...
public function execute(\Magento\Framework\Event\Observer $observer){
if($block = $observer->getEvent()->getBlock()){
….
if($block instanceof \Magento\Catalog\Block\Adminhtml\Category\Checkboxes\Tree){
$block->setTemplate('Web4pro_Defaultproduct::tree.phtml');
}
}
}
}
The new template will look as follows:
<?php $_divId = 'tree-div_' . time() ?>
<div id="<?= /* @escapeNotVerified */ $_divId ?>" class="tree"></div>
<script id="ie-deferred-loader" defer="defer" src="//:"></script>
<script>
require(["Web4pro_Defaultproduct/js/category-checkbox-tree"], function (element) {
element({
"dataUrl": "<?= /* @escapeNotVerified */ $block->getLoadTreeUrl() ?>" ,
"divId": "<?= /* @escapeNotVerified */$_divId ?>",
"rootVisible": <?php if ($block->getRoot()->getIsVisible()): ?>true<?php else : ?>false<?php endif; ?>,
"useAjax": <?= /* @escapeNotVerified */ $block->getUseAjax() ?>,
"currentNodeId": <?= (int)$block->getCategoryId() ?>,
"jsFormObject": <?= /* @escapeNotVerified */ $block->getJsFormObject() ?>,
"name": "<?= /* @escapeNotVerified */ htmlentities($block->getRoot()->getName()) ?>",
"checked": "<?= /* @escapeNotVerified */ $block->getRoot()->getChecked() ?>",
"allowDrop": <?php if ($block->getRoot()->getIsVisible()): ?>true<?php else : ?>false<?php endif; ?>,
"rootId": <?= (int)$block->getRoot()->getId() ?>,
"expanded": <?= (int)$block->getIsWasExpanded() ?>,
"categoryId": <?= (int)$block->getCategoryId() ?>,
"treeJson": <?= /* @escapeNotVerified */ $block->getTreeJson() ?>
});
})
<
The new component will look as follows:
define([
'jquery',
'prototype',
'extjs/ext-tree-checkbox',
'mage/adminhtml/form'
], function (jQuery) {
'use strict';
return function (config) {
var tree,
options = {
dataUrl: config.dataUrl,
divId: config.divId,
rootVisible: config.rootVisible,
useAjax: config.useAjax,
currentNodeId: config.currentNodeId,
jsFormObject: config.jsFormObject,
name: config.name,
checked: config.checked,
allowDrop: config.allowDrop,
rootId: config.rootId,
expanded: config.expanded,
categoryId: config.categoryId,
treeJson: config.treeJson
},
data = {},
parameters = {},
root = {},
len = 0,
key = '',
i = 0;
/* eslint-disable */
/**
* Fix ext compatibility with prototype 1.6
*/
Ext.lib.Event.getTarget = function (e) {// eslint-disable-line no-undef
var ee = e.browserEvent || e;
return ee.target ? Event.element(ee) : null;
};
/**
* @param {Object} el
* @param {Object} config
*/
Ext.tree.TreePanel.Enhanced = function (el, config) {// eslint-disable-line no-undef
Ext.tree.TreePanel.Enhanced.superclass.constructor.call(this, el, config);// eslint-disable-line no-undef
};
Ext.extend(Ext.tree.TreePanel.Enhanced, Ext.tree.TreePanel, {// eslint-disable-line no-undef
/* eslint-enable */
/**
* @param {Object} config
* @param {Boolean} firstLoad
*/
loadTree: function (config, firstLoad) {// eslint-disable-line no-shadow
parameters = config.parameters,
data = config.data,
root = new Ext.tree.TreeNode(parameters);// eslint-disable-line no-undef
if (typeof parameters.rootVisible != 'undefined') {
this.rootVisible = parameters.rootVisible * 1;
}
this.nodeHash = {};
this.setRootNode(root);
if (firstLoad) {
this.addListener('click', this.categoryClick.createDelegate(this));
}
this.loader.buildCategoryTree(root, data);
this.el.dom.innerHTML = '';
// render the tree
this.render();
},
/**
* @param {Object} node
*/
categoryClick: function (node) {
node.getUI().check(!node.getUI().checked());
}
});
jQuery(function () {
var categoryLoader = new Ext.tree.TreeLoader({// eslint-disable-line no-undef
dataUrl: config.dataUrl
});
/**
* @param {Object} response
* @param {Object} parent
* @param {Function} callback
*/
categoryLoader.processResponse = function (response, parent, callback) {
config = JSON.parse(response.responseText);
this.buildCategoryTree(parent, config);
if (typeof callback === 'function') {
callback(this, parent);
}
};
/**
* @param {Object} config
* @returns {Object}
*/
categoryLoader.createNode = function (config) {// eslint-disable-line no-shadow
var node;
config.uiProvider = Ext.tree.CheckboxNodeUI;// eslint-disable-line no-undef
if (config.children && !config.children.length) {
delete config.children;
node = new Ext.tree.AsyncTreeNode(config);// eslint-disable-line no-undef
} else {
node = new Ext.tree.TreeNode(config);// eslint-disable-line no-undef
}
return node;
};
/**
* @param {Object} parent
* @param {Object} config
* @param {Integer} i
*/
categoryLoader.processCategoryTree = function (parent, config, i) {// eslint-disable-line no-shadow
var node,
_node = {};
config[i].uiProvider = Ext.tree.CheckboxNodeUI;// eslint-disable-line no-undef
_node = Object.clone(config[i]);
if (_node.children && !_node.children.length) {
delete _node.children;
node = new Ext.tree.AsyncTreeNode(_node);// eslint-disable-line no-undef
} else {
node = new Ext.tree.TreeNode(config[i]);// eslint-disable-line no-undef
}
parent.appendChild(node);
node.loader = node.getOwnerTree().loader;
if (_node.children) {
categoryLoader.buildCategoryTree(node, _node.children);
}
};
/**
* @param {Object} parent
* @param {Object} config
* @returns {void}
*/
categoryLoader.buildCategoryTree = function (parent, config) {// eslint-disable-line no-shadow
if (!config) {
return null;
}
if (parent && config && config.length) {
for (var i = 0; i < config.length; i ) {
categoryLoader.processCategoryTree(parent, config, i);
}
}
};
/**
*
* @param {Object} hash
* @param {Object} node
* @returns {Object}
*/
categoryLoader.buildHashChildren = function (hash, node) {// eslint-disable-line no-shadow
// eslint-disable-next-line no-extra-parens
if ((node.childNodes.length > 0) || (node.loaded === false && node.loading === false)) {
hash.children = [];
for (i = 0, len = node.childNodes.length; i < len; i ) {
/* eslint-disable */
if (!hash.children) {
hash.children = [];
}
/* eslint-enable */
hash.children.push(this.buildHash(node.childNodes[i]));
}
}
return hash;
};
/**
* @param {Object} node
* @returns {Object}
*/
categoryLoader.buildHash = function (node) {
var hash = {};
hash = this.toArray(node.attributes);
return categoryLoader.buildHashChildren(hash, node);
};
/**
* @param {Object} attributes
* @returns {Object}
*/
categoryLoader.toArray = function (attributes) {
data = {};
for (key in attributes) {
if (attributes[key]) {
data[key] = attributes[key];
}
}
return data;
};
categoryLoader.on('beforeload', function (treeLoader, node) {
treeLoader.baseParams.id = node.attributes.id;
});
/* eslint-disable */
categoryLoader.on('load', function () {
varienWindowOnload();
});
tree = new Ext.tree.TreePanel.Enhanced(options.divId, {
animate: false,
loader: categoryLoader,
enableDD: false,
containerScroll: true,
selModel: new Ext.tree.CheckNodeMultiSelectionModel(),
rootVisible: options.rootVisible,
useAjax: options.useAjax,
currentNodeId: options.currentNodeId,
addNodeTo: false,
rootUIProvider: Ext.tree.CheckboxNodeUI
});
tree.on('check', function (node) {
options.jsFormObject.updateElement.value = this.getChecked().join(', ');
varienElementMethods.setHasChanges(node.getUI().checkbox);
}, tree);
// set the root node
//jscs:disable requireCamelCaseOrUpperCaseIdentifiers
parameters = {
text: options.name,
draggable: false,
checked: options.checked,
uiProvider: Ext.tree.CheckboxNodeUI,
allowDrop: options.allowDrop,
id: options.rootId,
expanded: options.expanded,
category_id: options.categoryId
};
//jscs:enable requireCamelCaseOrUpperCaseIdentifiers
tree.loadTree({
parameters: parameters, data: options.treeJson
}, true);
/* eslint-enable */
});
};
});
As you can see, it differs from the original by only one line. However, now all categories created are available when editing the pricing rule.
Amasty_Rewards 1.5.0. Fixing a Checkout Bug
Amasty provides a useful module, Amasty_Rewards, for store loyalty program. This extension lets administrators ability to configure rules for how customers will accrue Reward Points (usually for previously created orders). Customers can use these points to get discounts on future orders.
Let’s say you have a site on Magento® 2 and this module has been working since its first version. After upgrading from Amasty 1.2.2 to 1.5.0, you’re pleased to see a new component for using points on the checkout page. Before, a customer could only set the desired number of points on the cart page, and a custom component was implemented for checkout. A custom component was immediately deleted since it would be no longer needed. However, a bug was identified in the component from Amasty. We describe it below.
Let’s say a customer has 100 points. In the configuration, a Point Rate of 20 is set, meaning 20 points translate to a $1 discount, and 1 point gives the customer a $0.05 discount. After submitting a form (using AJAX), the number of points in the form is changed to 0.05, and the text below the input field incorrectly says, “You have 99.95 points left,” while the discount amount is calculated correctly as $0.05.
Next, we will determine the cause of the bug and show how to fix it.
Investigating the Reason for the Bug at Checkout
The following was established after analyzing the component. The component itself is defined as follows:
<referenceBlock name="checkout.root">
<arguments>
<argument name="jsLayout" xsi:type="array">
<item name="components" xsi:type="array">
<item name="checkout" xsi:type="array">
<item name="children" xsi:type="array">
<item name="steps" xsi:type="array">
<item name="children" xsi:type="array">
<item name="billing-step" xsi:type="array">
<item name="component" xsi:type="string">uiComponent</item>
<item name="children" xsi:type="array">
<item name="payment" xsi:type="array">
<item name="children" xsi:type="array">
<item name="afterMethods" xsi:type="array">
<item name="children" xsi:type="array">
<item name="rewards" xsi:type="array">
<item name="component" xsi:type="string">Amasty_Rewards/js/view/checkout/payment/rewards</item>
<item name="sortOrder" xsi:type="string">10</item>
<item name="children" xsi:type="array">
<item name="errors" xsi:type="array">
<item name="sortOrder" xsi:type="string">0</item>
<item name="component" xsi:type="string">Amasty_Rewards/js/view/checkout/payment/reward-messages</item>
<item name="displayArea" xsi:type="string">messages</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</argument>
</arguments>
</referenceBlock>
Its main part is the Javascript file Amasty_Rewards/js/view/checkout/payment/rewards and the knockout template Amasty_Rewards/checkout/payment/rewards
. There is also a child component that displays messages, but we aren’t considering it now. Below is the code for the files (knockout component and knockout template) mentioned above:
define([
'jquery',
'ko',
'uiComponent',
'Magento_Checkout/js/model/quote',
'Amasty_Rewards/js/action/add-reward',
'Amasty_Rewards/js/action/cancel-reward'
], function ($, ko, Component, quote, setRewardPointAction, cancelRewardPointAction) {
'use strict';
var pointsUsed = ko.observable(null),
pointsLeft = ko.observable(null),
isApplied;
isApplied = ko.observable(pointsUsed() != null);
return Component.extend({
defaults: {
template: 'Amasty_Rewards/checkout/payment/rewards'
},
/**
* Applied flag
*/
isApplied: isApplied,
pointsLeft: pointsLeft,
/**
*
* @return {exports}
*/
initialize: function() {
this._super();
pointsUsed(this.pointsUsed);
pointsLeft(this.pointsLeft);
if (pointsUsed() > 0) {
isApplied(true);
}
return this;
},
/**
* @return {*|Boolean}
*/
isDisplayed: function () {
return this.customerId;
},
/**
* Coupon code application procedure
*/
apply: function () {
if (this.validate()) {
pointsUsed(this.pointsUsed);
setRewardPointAction(pointsUsed, isApplied, this.applyUrl, pointsLeft);
}
},
/**
* Cancel using coupon
*/
cancel: function () {
var points = pointsUsed();
pointsUsed(0);
cancelRewardPointAction(isApplied, this.cancelUrl);
pointsLeft(this.pointsLeft Number.parseFloat(points));
},
/**
*
* @return {*}
*/
getRewardsCount: function () {
return pointsLeft;
},
/**
*
* @return {*}
*/
getPointsRate: function () {
return this.pointsRate;
},
/**
*
* @return {*}
*/
getCurrentCurrency: function () {
return this.currentCurrencyCode;
},
/**
*
* @return {*}
*/
getRateForCurrency: function () {
return this.rateForCurrency;
},
/**
* Coupon form validation
*
* @returns {Boolean}
*/
validate: function () {
var form = '#discount-reward-form';
var valueValid = (this.pointsLeft - this.pointsUsed >= 0) && this.pointsUsed > 0;
return $(form).validation() && $(form).validation('isValid') && valueValid;
}
});
});
As you can see, the template has an input field and two buttons: “Apply Reward” and “Cancel Reward.” Only one of them is visible at any given time, depending on whether or not the user has entered a number of points to use. When the button is clicked, the component method applies or cancel is applied accordingly. Then the apply method calls the setRewardPointAction function, which is implemented in Amasty_Rewards/js/action/add-reward
. This function passes the pointsUsed and pointsLeft variables as a knockout parameter. Let’s analyze the code of this function:
/**
* Customer store credit(balance) application
*/
define([
'ko',
'jquery',
'Magento_Checkout/js/model/quote',
'Magento_Checkout/js/model/resource-url-manager',
'Magento_Checkout/js/model/error-processor',
'Amasty_Rewards/js/model/payment/reward-messages',
'mage/storage',
'mage/translate',
'Magento_Checkout/js/action/get-payment-information',
'Magento_Checkout/js/model/totals',
'Magento_Checkout/js/model/full-screen-loader'
], function (ko, $, quote, urlManager, errorProcessor, messageContainer, storage, $t, getPaymentInformationAction,
totals, fullScreenLoader
) {
'use strict';
return function (pointsUsed, isApplied, applyUrl, pointsLeftObs) {
var discountAmount = quote.totals().discount_amount,
url = applyUrl 'amreward_amount/' encodeURIComponent(pointsUsed());
fullScreenLoader.startLoader();
return storage.put(
url,
{},
false
).done(function (response) {
var deferred;
if (response) {
deferred = $.Deferred();
isApplied(true);
totals.isLoading(true);
getPaymentInformationAction(deferred);
$.when(deferred).done(function () {
pointsUsed(Math.abs(totals.totals().discount_amount) - discountAmount);
pointsLeftObs(pointsLeftObs() - pointsUsed());
$('#amreward_amount').val(pointsUsed()).change();
messageContainer.addSuccessMessage({
'message': $t('You used ' pointsUsed() ' point(s)')
});
fullScreenLoader.stopLoader();
totals.isLoading(false);
});
}
}).fail(function (response) {
fullScreenLoader.stopLoader();
totals.isLoading(false);
errorProcessor.process(response, messageContainer);
});
};
});
As you can see, the code sends a request to the server for applying points. Next, according to the response, getPaymentInformation() is called to get updates to totals and methods of payment. Then, for some reason, the discount_amount value received is recorded as the number of points used. This would be accurate if the customer received a $1 discount for 1 point; however, when the customer gets only $0.05 for 1 point (see the previously-configured discount calculation rule) this logic is incorrect. It seems that Amasty did not consider this case. It would be more logically sound to receive the number of used and remaining points from the server, but Amasty decided not to implement a separate controller to do this, which would have returned JSON. In any event, the problem must be solved.
Fixing the Checkout Bug in Amasty_Rewards 1.5.0 and 1.6.0
This fix is made up of two parts: a server part and a browser part. In Magento 2, the totals class implements the Magento\Quote\Api\Data\TotalsInterface interface and supports extension attributes. Since we don’t need to save the extension attributes on the server side and use the built-in attribute joiner, we define a new extension attribute as follows (extension_attributes.xml file).
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Api/etc/extension_attributes.xsd">
<extension_attributes for="Magento\Quote\Api\Data\TotalsInterface">
<attribute code="reward" type="Web4pro\Ajaxcart\Model\Reward"/>
</extension_attributes>
</config>
Class Web4pro\Ajaxcart\Model\Reward will look as follows:
class Reward extends \Magento\Framework\DataObject
{
/**
* @param int $pointsLeft
* @return $this
*/
public function setPointsLeft($pointsLeft){
return $this->setData('pointsLeft',$pointsLeft);
}
/**
* @return int|null
*/
public function getPointsLeft(){
return $this->getData('pointsLeft');
}
/**
* @param int $pointsUsed
* @return $this
*/
public function setPointsUsed($pointsUsed){
return $this->setData('pointsUsed',$pointsUsed);
}
/**
* @return int|null
*/
public function getPointsUsed(){
return $this->getData('pointsUsed');
}
}
Now we add the information about the client’s points in totals. We can do this using the plugin.
<type name="Magento\Quote\Model\Cart\CartTotalRepository">
<plugin name="provide-reward" type="Web4pro\Ajaxcart\Model\Plugin" sortOrder="20"/>
</type>
class Plugin
{
protected $_helper;
protected $_reward;
protected $_objectManager;
public function __construct(\Amasty\Rewards\Helper\Data $helper,
\Magentice\Ajaxcart\Model\Reward $reward,
\Magento\Framework\ObjectManagerInterface $objectManager){
$this->_helper = $helper;
$this->_reward = $reward;
$this->_objectManager = $objectManager;
}
public function afterGet($model,$quoteTotals){
$rewardsData = $this->_helper->getRewardsData();
if(isset($rewardsData['pointsLeft'])){
$extensionAttributes = $quoteTotals->getExtensionAttributes();
if(!$extensionAttributes){
$extensionAttributes = $this->_objectManager->create('Magento\Quote\Api\Data\TotalsExtension');
}
$this->_reward->setPointsLeft($rewardsData['pointsLeft'])->setPointsUsed($rewardsData['pointsUsed']);
$extensionAttributes->setReward($this->_reward);
$quoteTotals->setExtensionAttributes($extensionAttributes);
}
return $quoteTotals;
}
}
As you can see, the information about points used and remaining was successfully added to the totals extension attribute and is passed to the front end. Now we have to process this information on the front end. This is where we ran into some difficulties. The knockout variables pointsUsed and pointsLeft aren’t visible outside the Amasty component, and as such, it isn’t possible to redefine the method that uses them. It’s also difficult to replace the Amasty_Rewards/js/action/add-reward function.
To fix this problem, we can create event handlers for changing the knockout variables. The totals variable of the componentMagento_Checkout/js/model/totals
is one of these variables.
We replace the component’s Javascript file using the layout file checkout_index_index.xml.
<referenceBlock name="checkout.root">
<arguments>
<argument name="jsLayout" xsi:type="array">
<item name="components" xsi:type="array">
<item name="checkout" xsi:type="array">
<item name="children" xsi:type="array">
<item name="steps" xsi:type="array">
<item name="children" xsi:type="array">
<item name="billing-step" xsi:type="array">
<item name="component" xsi:type="string">uiComponent</item>
<item name="children" xsi:type="array">
<item name="payment" xsi:type="array">
<item name="children" xsi:type="array">
<item name="afterMethods" xsi:type="array">
<item name="children" xsi:type="array">
<item name="rewards" xsi:type="array">
<item name="component" xsi:type="string">Web4pro_Ajaxcart/js/checkout/reward</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</argument>
</arguments>
</referenceBlock>
The component's new file will extend the existing file and looks as follows:
define(["jquery",'mage/translate','Amasty_Rewards/js/view/checkout/payment/rewards','Magento_Checkout/js/model/totals'],
function($,$t,Component,totals){
return Component.extend({
initialize:function(){
var self = this;
totals.totals.subscribe(function(data) {
self.reward = data.extension_attributes.reward;
self.pointsUsed = self.reward.points_used;
self.pointsLeft = self.reward.points_left;
var messages = self.regions.messages();
messages[0].messageContainer.successMessages.subscribe(function(data){
if(data.length){
self.pointsUsed = self.reward.points_used;
self.pointsLeft = self.reward.points_left;
if(data[0].search($t('You used'))!=-1&&data[0].search($t('You used ' self.reward.points_used))==-1){
messages[0].messageContainer.clear();
messages[0].messageContainer.addSuccessMessage({
'message': $t('You used ' self.pointsUsed ' point(s)')
});
self.initialize();
$('#amreward_amount').val(self.pointsUsed).change();
}
}
});
});
this._super();
return this;
}
});
});
<!-- ko if: isDisplayed() -->
<div class="payment-option _collapsible opc-payment-additional rewards-add" data-bind="mageInit: {'collapsible':{'openedState': '_active'}}">
<div class="payment-option-title field choice" data-role="title">
<span class="action action-toggle" id="block-reward-heading" role="heading" aria-level="2">
<!-- ko i18n: 'Apply Rewards'--><!-- /ko -->
</span>
</div>
<div class="payment-option-content" data-role="content" aria-labelledby="block-reward-heading">
<!-- ko foreach: getRegion('messages') -->
<!-- ko template: getTemplate() --><!-- /ko -->
<!--/ko-->
<div class="pointsLeft" data-role="title">
<!-- ko i18n: 'You Have '--><!-- /ko -->
<strong data-bind="text: getRewardsCount()"></strong>
<!-- ko i18n: ' points left '--><!-- /ko -->
</div>
<div class="pointsRate" data-role="title">
<span data-bind="text: getPointsRate()"></span>
<!-- ko i18n: ' for every'--><!-- /ko -->
<span data-bind="text: getRateForCurrency()"></span>
<span data-bind="text: getCurrentCurrency()"></span>
</div>
<form class="form form-reward" id="discount-reward-form">
<div class="payment-option-inner">
<input type="hidden" name="remove" id="remove-amreward" value="0" />
<div class="field">
<div class="control">
<input class="input-text"
type="text"
id="amreward_amount"
name="amreward_amount"
data-validate="{'required-entry':true}"
data-bind="value: pointsUsed, attr:{placeholder: $t('Enter reward amount')} " />
</div>
</div>
<div class="actions-toolbar reward-actions">
<div class="primary">
<!-- ko ifnot: isApplied() -->
<button class="action action-apply" type="submit" data-bind="'value': $t('Apply Reward'), click: apply">
<span><!-- ko i18n: 'Apply Reward'--><!-- /ko --></span>
</button>
<!-- /ko -->
<!-- ko if: isApplied() -->
<button class="action action-cancel" type="submit" data-bind="'value': $t('Cancel Reward'), click: cancel">
<span><!-- ko i18n: 'Cancel Reward'--><!-- /ko --></span>
</button>
<!-- /ko -->
</div>
</div>
</div>
</form>
</div>
</div>
<!-- /ko -->
As you can see, we implemented an event handler for changing totals. However, that’s not enough. Immediately after executing the handler for changing totals, the callback from Amasty_Rewards/js/action/add-reward
is executed, and the value of the knockout variables changes. The incorrect values are also displayed in the browser. But since the code above in Amasty_Rewards/js/action/add-reward also initializes the message for the messages child component, we can use its knockout variable to create a handler. This will also allow us to display the correct message about the client’s points. The self.initialize() call sets the required values for the knockout variables from the parent code.
We also must note that this bug in the Amasty_Rewards module wasn’t fixed in Amasty version 1.6.0, but the resolution described above only works for Magento versions 2.2.4 and later. When installing Amasty_Rewards 1.6.0 on Magento 2.2.3, the component installed threw a Javascript error on the checkout page in the browser console: “reward.js:10 Uncaught TypeError: Cannot read property ‘reward’ of undefined”
The cause of this problem is on the back end. What happened is that starting with some version, the Amasty_Rewards module depends on Amasty_Conditions
, but in Amasty_Conditions the plugin was implemented in Magento\Quote\Model\Cart\CartTotalRepository
the following way:
public function aroundGet(\Magento\Quote\Model\Cart\CartTotalRepository $subject, \Closure $proceed, $cartId)
{
if (version_compare($this->productMetadata->getVersion(), '2.2.4', '>=')) {
return $proceed($cartId);
}
/** @var \Magento\Quote\Model\Quote $quote */
$quote = $this->quoteRepository->getActive($cartId);
if ($quote->isVirtual()) {
$addressTotalsData = $quote->getBillingAddress()->getData();
$addressTotals = $quote->getBillingAddress()->getTotals();
} else {
$addressTotalsData = $quote->getShippingAddress()->getData();
$addressTotals = $quote->getShippingAddress()->getTotals();
}
unset($addressTotalsData[\Magento\Framework\Api\ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]);
/** @var \Magento\Quote\Api\Data\TotalsInterface $quoteTotals */
$quoteTotals = $this->totalsFactory->create();
$this->dataObjectHelper->populateWithArray(
$quoteTotals,
$addressTotalsData,
\Magento\Quote\Api\Data\TotalsInterface::class
);
$items = [];
foreach ($quote->getAllVisibleItems() as $index => $item) {
$items[$index] = $this->itemConverter->modelToDataObject($item);
}
$calculatedTotals = $this->totalsConverter->process($addressTotals);
$quoteTotals->setTotalSegments($calculatedTotals);
$amount = $quoteTotals->getGrandTotal() - $quoteTotals->getTaxAmount();
$amount = $amount > 0 ? $amount : 0;
$quoteTotals->setCouponCode($this->couponService->get($cartId));
$quoteTotals->setGrandTotal($amount);
$quoteTotals->setItems($items);
$quoteTotals->setItemsQty($quote->getItemsQty());
$quoteTotals->setBaseCurrencyCode($quote->getBaseCurrencyCode());
$quoteTotals->setQuoteCurrencyCode($quote->getQuoteCurrencyCode());
if ($this->isEnterprise()) {
$quoteTotals = $this->setExtensionAttributes($quoteTotals, $quote);
}
return $quoteTotals;
}
As you can see, this plugin checks the Magento version, and for versions less than 2.2.4 it implements its own code, blocking the execution of further plugins. As such, the extension attribute implemented in our plugin doesn’t even have the chance to be defined and passed to the front end. We understand why this plugin was implemented. The CartTotalRepository class had a completely different implementation until version 2.2.4, and this could create problems for a full cross-version implementation of the Amasty extension. In any event, we had to correct the above error of passing the extension attribute to the front end in case, for some reason, it isn’t possible to upgrade to newer versions of Magento. This can be done by adding the following plugin:
<type name="Magento\Quote\Model\Cart\Totals">
<plugin name="add-gift-total" type="Web4pro\Ajaxcart\Model\Plugin" sortOrder="20"/>
</type>
public function afterSetItems($quoteTotals){
$rewardsData = $this->_helper->getRewardsData();
if(isset($rewardsData['pointsLeft'])&&version_compare($this->productMetadata->getVersion(), '2.2.4', '<')){
$extensionAttributes = $quoteTotals->getExtensionAttributes();
if(!$extensionAttributes){
$extensionAttributes = $this->_objectManager->create('Magento\Quote\Api\Data\TotalsExtension');
}
$this->_reward->setPointsLeft($rewardsData['pointsLeft'])->setPointsUsed($rewardsData['pointsUsed']);
$extensionAttributes->setReward($this->_reward);
$quoteTotals->setExtensionAttributes($extensionAttributes);
}
return $quoteTotals;
}
5 Advantages of Magento Mobile Site in M-Commerce Era
There’s no doubt that mobile sites are being used more and more often. To accommodate for the shift, eCommerce sites are becoming mobile-friendly. This allows them to increase their reach and generate more sales than ever before. Below, we’re going to discuss the benefits of the Magento® mobile site. But first, we should understand what is the mobile commerce and why having a mobile site is necessary for any eCommerce business.
What is M-Commerce?
When we talk about M-Commerce, we’re thinking of shopping with mobile phones. Since nearly everyone carries phones in their pockets, using this tool will allow eCommerce merchants to expand their reach.
M-Commerce is thought to be the next trend in online shopping and it can be done through the use of tablets, cell phones, laptops, and any other mobile devices. Since Europe uses micro-browsers, the country uses it more than the United States even does.
Now, why is M-Commerce so popular? Customers enjoy the convenience of using mobile sites rather than having to displace themselves to buy items at the store. Of course, it is much more convenient to order anything from your phone rather than trying to reach the computer at home or work, because people always have their phones on the go.
One more point for the mobile shopping is that you can reach your customers via social network and than attract to your site. In this case, your efforts will be rewarded twice more. Customers may find your company on Instagram, for example, and then they can download the app or having a fast mobile version of your site and start order items.
The Growth of Mobile Shopping
There’s a growing number of people who avoid the shopping process in real life, but who enjoy shopping online. That’s because shopping online takes less effort for the shopper and it often provides more diversity regarding services and products.
Mobiles are used notoriously across the planet. Out of everyone who has a smartphone, more than half of these people pick up their phone within the first few minutes of their morning. Not only this, but smartphone apps make up for nearly 90% of mobile media while websites account for the rest of mobile media use. According to Statcounter, mobile usage market share is 53% comparing to 43% of desktop usage, and only 4% of the tablet worldwide. There are some more benefits of mobile-oriented sites and one of them is payment protection.
Advantages of Mobile Payments
There are two reasons why customers enjoy using mobile payments: convenience and safety. Since you can carry your money with your phone, you don’t have to worry about losing your cash; as such, mobile payments reduce the risk of you being the victim of theft. Also, since your credit card information is stored in the Cloud, and security standards are held, it is the safest way to keep your money. Mobile payment doesn’t store your credit card information so the possibility of this information being hacked is also reduced. Let’s move on to the stats and see much of advantage from the mobile-oriented business.
Mobile Commerce Statistics
AppJetty confirms that M-Commerce has already generated 132.69 billion dollars in sales this year. Not only this, but the site points out that there are 7.7 Billion mobile connections and 4.7 Billion mobile subscribers. By using M-Commerce, you can significantly expand your reach.
We see that the growth of mobile commerce is stable and will continue to bring profit to businesses. Now, what about Magento sites? Are merchants ready for changes? Did they start to follow the mobile commerce trend? Next, we will talk about the benefits of Magento mobile experience and which features exist to optimize your store for mobile devices.
5 Advantages of Magento Mobile Optimization
Magento has made significant strides in Magento mobile development. Because of this, there are also advantages that come with using Magento for M-Commerce.
Magento 2 Mobile Experience
No matter what, it’s important that your customers’ experiences are the best possible. When they visit your site, they need to leave feeling like they’ve made a good decision with their purchases; after all, that’s how they’ll keep coming back for more.
Omnichannel Experience
Magento allows you to optimize an omnichannel experience to ensure your customers are satisfied. You can use Magento to keep track of the inventory of your physical store and in your warehouse with the same dashboard. This ensures you won’t have the same item ordered twice and that you won’t sell more than you have in stock.
You can also connect multiple social media sites to your store with Magento extensions. If you have a Facebook, Instagram, or Youtube profile, you can link them all back to your store. When you do this, you can expand your reach and have your followers buy the products they want with more ease. Rather than looking you up on Google, they can click on a link and be brought right to you.
Useful for you:
POS Mobile Version
The point of sale system (POS) is the moment when a customer buys a product from your company. It manages the transactions of your business and ensures that all of your sales go smoothly.
The major benefit of having a POS system is that all of your inventory is located in the same place. You can see both inventory and sales from the same dashboard, which makes it much easier to control.
Useful for you:
Mobile API
Magento 2 has introduced a number of APIs to improve your store’s functionality, features, and designs.
Admin Panel
Magento 2’s admin panel is a major step up compared to Magento 1. Originally, users and merchants found it hard to create their sites without developers. That’s because customizing sites required more coding on their end than Magento 2. Now, you can use Magento mobile admin panel to customize your site and is easier, overall, for any backend users.
Mobile Marketing Features
Magento 2 has some of the best features that you can ask for if you have a mobile-adapted site.
- You can target your customers depending on the age, gender, history, and location to provide them with offers that might interest them.
- You can make every shopping visit unique by customizing and segmenting every experience.
- Set your promotions with certain limitations or conditions. That means offers can be set with timeframes to provide your customers with a sense of urgency; thereby, causing them to buy more quickly and increase your conversions.
- By setting up personalized categories, any website can be more convenient. If you have a clothing store, you can separate clothing into different categories and have subcategories to follow those.
- Merchants have the opportunity to customize their site on their own with Magento 2 because they have a drag-and-drop option that allows them to place items where they want.
- Magento 2 customizing emails ensures that every customer gets a newsletter that’s tailored for them. If you know that this person enjoys shopping, you can provide him or her with a discount. Since your customer is inclined to shop, this discount will likely get them to come to your store again.
These were the main features to use in the mobile version of the Magento store. Functionality is extendable due to the system’s flexibility. That is why everything depends on your primary goals. You can choose between mobile optimization, app creation or you will go with PWA version of your site. In any case, going mobile will be great for your business growth.
How to Add Custom Field in Magento 2 Registration Form
Custom field to Magento registration form can be added by adding custom block to the container form_additional_info to handle customer_account_create with this custom field. Example customer_account_create.xml
<?xml version="1.0"?> <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"> <body> <referenceContainer name="form_additional_info"> <block name="customer.register.additional.field" class="Web4pro\Customer\Block\Additional" template="Web4pro_Customer::additional.phtml"/> </referenceContainer> </body> </page>
After field is added, code for storing customer’s input should be implemented. It’s possible to with observer on event customer_register_success or by adding attribute to customer entity and adding it to customer_account_create form. If attribute value should be shown on customer edit form in admin, it should be also added to adminhtml_customer. Also field with attribute code should be added to view/adminhtml/ui_component/customer_form.xml in this case.
Tips to Improve your Magento 2 Store Performance
When it comes to Magento® 2 experience, owners of Magento 2 stores really loving the convenience it provides. However, we have also found users forcing the performance issues of stores. Basically, there are plenty of ways to fully utilize the amenities Magento 2 store can provide.
In this article, we will talk about some of the Magento performance optimization tips so that you can use it to increase the efficiency of your overall business model.
How to Manage Store in Magento 2
When it comes to increasing the profitability of a business, understand that efficiency is the key. We realize that it can be difficult at times to manage Magento 2 store especially if you are unaware of the utility of all its features.
First, let’s talk about some of the technical aspects. Modern servers along with latest PHP are a must to manage a store in Magento 2. Please pay attention to whether the Apache/Nginx version is the one that you need. When you are looking for hosting, you must look for clarification if that supports Magento or not. It makes the task of optimizing much easier. If you do not have budget constraints, we would recommend you to go with a dedicated hosting solution. Cloud hosting is usually used if you are on a budget, but it does serve the purpose to a certain extent.
Performance optimized template or conversion optimized template are some of the buzzwords that you will hear when you are affiliated with an eCommerce platform. Although do keep in mind that taking a high-performance template does not jeopardize with Magento 2 performance.
Updating Magento core and extensions are important. Before the update, we would strongly suggest that you keep a backup of all your important data.
Magento 2 Performance Toolkit
You would be pleasantly surprised to know the attributes you can utilize to improve performance. Magento 2 toolkit provides for a better experience for the website in terms of both front-end and back-end performance.
There is an inbuilt performance toolkit in Magento 2, but it is also compatible with Magento 1 version. Based on the profile that you choose you will have your data generated in that way. For benchmarking the backend performance, NewRelic can be a useful tool. For modification purposes, we would recommend Gatling or JMeter.
For the frontend performance, speed is of the essence. For Magento 2 performance boost, you need to ensure that your page loads fast and all the relevant information can be easily accessed by the customers. For a speedy performance of your website, go to the Magento dashboard to minimize and merge the CSS and JavaScript of your website.
Magento Product Management Tool
Magento product management tools basically facilitate merchants to automate various manual functions. In this paragraph, we will talk about some of the great features that you utilize to boost the overall performance of your site.
Multistore Selection
For an international eCommerce platform, you can clearly understand that having provision for multiple stores is always a plus point. We would recommend that you will have multiple stores in each country where you operate.
Magento 2 has out-of-the-box multistore feature, and you can run multiple websites easily. Everything is controlled from the admin panel. For the installation, you need a developer help. But you can also choose to create separate product descriptions and target.
Implement Bulk Import Option
When it comes to multiple product ranges, bulk import option is a boon to the Magento store owners. We would highly recommend implementing the bulk import option in your website. With some affordable extensions, you can easily import product data together in a CSV file. However, we would suggest that you clearly understand the formatting basics first before implanting this option.
Advanced Inventory Management
Magento offers the provision to create an advanced inventory management. If your product is unavailable most of the time, it becomes difficult to retain the customers. If a product is unavailable at the moment, showing a time frame of when the customer can order it again can be useful at times. You can also use the POS system and work effectively on both physical and online store, and track all your inventories.
Product Management
Product management means showing the right features of the product to the customers. Communicating the relevant information of the product is important. Make sure you update the product descriptions from time to time with the changing trends and customer needs. Usually, the product management tool shows all the products in the form of a table. It provides quite less provision in terms of modification features. You can go for an extended product grid that will help you categorize the data based on your own choice and edit the data with easy drag and drop options. This will help to better navigation on your site and overall look and feel, so customers would go to the certain sections and won’t search for a desired product for too long.
Mobile Experience Option
Adding a mobile version is now a must for eCommerce platforms. A large portion of online purchases is done through smartphones and tablets. Hence, creating a mobile app or making a mobile version of your website is extremely important. A normal web version of the site would take a considerable amount of time to load. You will need to speed up the timing for loading the page on mobile. You can do that through reducing page size through GZIP or simply creating an app suited for Magento 2 store.
Useful for you:
Improve Magento 2 Performance for Success
To improve Magento 2 performance, one of the most useful tools is gZip compression. Customers are the one who would help you sustain your online business. eCommerce store owners would realize how difficult it can become to retain customers. User-friendly web page and fast process are two of the most important criteria for successful customer gain and retention. Other than that image optimization and creating a good visual appeal is equally important for successful marketing and sales.
Choosing from Top Payment Gateways for Magento in 2019
Online payments are a central feature of online business. When transaction information is processed, it’s routed through payment gateways. These act as an interface between your online business and the provider. In simple terms, this means that any successful eCommerce site depends on a payment gateway that handles purchases with speed, security, and convenience. Plus, they must provide features that make them accessible to your clients.
According to Statista, in March 2017, preferred methods of online payment were e-payments, credit cards, and debit cards. Add in mobile purchases and the percentage climbs above 90%. Successful online businesses rely on the right tools to process these payments. Here are all the details you’ll need to know about how to choose the best payment gateway for Magento® 2 platform.
How to Choose Magento 2 Payment Gateway
To choose the best Magento 2 payment gateway for your site, consider four requirements: convenience, capability, security, and pricing. Keep your clients happy and their information safe, and you’ll have more conversions and a higher profit. Look up for our recommendations below.
Which Edition of Magento Store Do You Have?
Magento Commerce (previously known as Magento Enterprise) is a paid product which costs 22,000$ per year. Magento Open Source (previously called Magento Community) is a free platform. Magento Commerce requires a bit of an investment at the outset, but over time, it will give you more options and a greater ease of access.
The edition of your store is not only the one factor when choosing your store functionality including payment options. We will consider several points: which payment options are available for customers, security standards, your business type, etc. Let’s move on to the details.
How Customers Will Perform Payments on Your Site?
Specific payment options are offered by each payment gateway. Most customers will prefer credit card options. Other popular payment options include online wallets like PayPal and mobile payments. It is important to understand your customers’ preferences. This lets you equip your convenient and simple options. This ensures satisfied customers and prevents lost sales. Customers also want to be safe when entering payment details, so choose payment form options carefully.
There are several options to process the purchase and they differ by security level and steps to complete the purchase. These are payment form with details form your server or straight from the browser or redirect.
Payment Form (Details on Your Server)
The payment form makes it easy and fast for clients to enter their payment data. It is inputted on your site where it will then be routed to the processor. However, security can be challenging with this option. Compliance with PCI standards requires serious and costly security precautions. The payment form is only cost-effective for large companies.
Payment Form (Details Straight from the Browser)
A third alternative is a payment form which gathers data and sends it directly to the processor. The details never enter your site, and this lowers the security demands. However, you retain a measure of responsibility for your payment client details. It will be important to understand standards for PCI data security to ensure you are in conformance.
Redirect
The redirect is the highest security option. A checkout form can be inserted into a secure iFrame on the website. Alternately, you can redirect clients to a purchasing page hosted by a secure purchaser. However, the form may not fit the formatting of the remainder of the website. This option is suitable for all companies, large or small. The processor is then entirely responsible for the security of your client’s information.
What Is The Contract Duration with Providers?
In considering providers, look into contract details. Some try to lock your customers in for two or more years after signing. Customers are often turned off by the need of a lengthy contract and wish to use them monthly instead. To keep your clients happy, familiarize yourself with contract options before including a provider on your platform.
Will You Offer PayPal?
Given the convenience and widespread use of PayPal, it’s a good idea to include it as a payment option on your site. Not every customer will be able to use it, but thankfully Magento allows you to offer two or several payment options. This means that you may want to use PayPal as a secondary payment option. It’s secure and widely trusted by consumers. An added benefit is that it can work as a backup if issues arise with merchant accounts or primary payment gateways.
Are You In ‘Hi-risk’ Business Category?
If the niche falls into a category of high-risk, then you may be limited in the choice of providers. Many prefer not to accommodate companies engaged in credit repair, diet programs, e-cigarettes, ebooks, debt collection, tobacco, travel, gambling, and adult content. If your business specializes in these niches, then you’ll need to find a payment provider willing to accommodate you.
Which Payment Methods Are Used by Your Target Audience?
Take into consideration your clients preferences, match this up with the online payment methods offered by your provider, and you’re good to go. It’s best to make sure that your providers have options to process debit card and credit cards. They will also need services for mobile payments and electronic transfer. Also, make sure to work with providers that are accessible to your clients’ countries.
How Many Payment Gateways Available for Magento?
Magento 2 payment gateway integration makes virtually all payment gateways accessible. Magento 2 users can make use of WorldPay, Paybox Direct, CyberSource, First Data, DIBS Payment Services, PAYON.de, Ogone, PSiGate, and eWay Direct, among others.
Useful for you:
Popular Payment Gateways for Magento 2
When you use Magento 2, it comes equipped with three default options of payment gateways. These are Braintree, PayPal, and Authorize.net. Gateway integration can be used to incorporate additional payment options. Here are reviews for the highest-rated gateways:
Paypal Payment Gateway Review
PayPal offers customized invoices and processes debit and credit cards. It is simple, quick, and safe, and authorization happens almost instantly. Plus, it offers currency conversion and is available in over 200 countries. However, PayPal can freeze an account without notice, and fees can be imposing for large sales volumes.
Magento Braintree Payment Gateway
Braintree is well designed and has no monthly fees, charging you only as per your use. It supports 3D secure and is accepted by 44 countries and using more than 130 currencies. It also offers optimized acceptance rates. The only real downside is that it doesn’t offer return fees for partial refunds.
You can configure PayPal and Braintree right from your admin panel. Just go to the Stores > Configuration > Sales Payment methods and then you will see all the available settings.
Stripe
Stripe works with debit card and credit card options. It also provides mobile payment and Bitcoin. The set-up is free and Stripe has no monthly or hidden fees. You can customize stripe with advanced reporting and unlimited plan options. However, it is not 3D secure, and you will be charged more if you customize gateway functionalities.
Google Checkout
One excellent payment gateway is Google Checkout. It offers fraud protection, simplicity, convenience, and extremely low fees. The fees begin as low as PayPal and become lower as sales increase over $3000 per month. However, clients must make their purchases through a Google account.
Amazon Payments
Amazon Payments are protected, simple, and quick, and they charge minimum transaction fees. An Amazon customer may use the data in their account to make purchases. It offers state of the art fraud detection and low transaction fees. Unfortunately, Amazon payments cannot be used outside the UK and the US.
Authorize.net
Authorize.net is an excellent solution, offering a free mobile app and 24/7 support. It accepts a wide variety of debit and credit cards and has fraud-fighting tools. It also securely stores client data so purchases are as easy as the click on a button. The downside is that it requires a fee of 25$ a month and the set-up of a merchant account.
Sage Pay
Sage Pay has the highest level of security and can accept all payment types, including PayPal. It also works with more than 25 currencies. It offers quick payments and a simple, easy to use interface. The downside is that it has a monthly charge, from $30-60 per month depending on the volume of sales.
Do You Need Custom Magento 2 Payment Gateway Integration?
PayPal, Braintree, and Authorize.net are offered with default Magento 2 integration. Custom payment gateway integration is needed for other providers. Compliance with PCI standards requires that no payment data is stored.
How to Add New Payment Method
With Magento 2, you can incorporate additional methods of payment with some additional steps. This requires the configuration of four elements: payment action, general payment method module options, payment method options, payment method facade. Methods of payment may be selected in the storefront or in the Admin, and they may be configured differently depending on the region. You can apply a method and behavior with keynotes.
Magento 2 Video Content Optimization
Magento® Product Video allows you to harness one of the most powerful features available on a website. A video can showcase products more effectively than pictures and text alone. Magento 2 video extensions offer a range of design options to customize the video content and thumbnails. It lets you build video galleries to display multiple videos on the same page. You can also customize each video gallery with sliders, grid panels, and thumb strips. This lets you pack loads of content onto a page while keeping it neat and clutter-free. Learn more about video content, options for Magento 2 store and how to work with it.
Why Is Video Content so Important for Sales?
The simple fact is that visitors to your site watch a video more than read a few lines of text. Plus, a few short minutes of video content can provide more information on your products than pages of text. Video content lets you showcase products from many angles.
By adding multimedia to a site, you can connect with more customers and dramatically boost conversion rates. Not only this, but most studies show that product or introductory video will likely to increase your sales. Check the related statistics below:
By including videos, you broaden the range of your site. Videos give you the option of offering recordings of events that showcase your products and services. Videos can also be used to provide tutorials, offering valuable content to your customers.
Videos are an excellent medium to offer consumer testimonials and user reviews. Customers will feel almost as if they are receiving live personal feedback. By using these multimedia features, you can build trust. And, trust is the single most important factor in promoting sales. Finally, multimedia content increases your search rankings, helping consumers to find your site more easily.
Useful for you:
Magento 2 Video Types
There are some different ways to place the video on your site. You can insert video from the external sites or have self-hosted videos in your store. Let’s consider which type of video content is easier to add to your Magento 2 store.
Magento 2 Embedded Videos
Magento video extension tools work with almost any format. MP4 video files are recommended first, as they are simple and extremely reliable. However, Magento works just as well with JPEG and PNG. MPEG, GIF, FMV, and SWF can be used as well, and this list is far from comprehensive.
Any of these formats can be uploaded from any device without a hassle. Plus, Magento works with nearly all platforms for video hosting. You can upload Vimeo and Youtube videos, plus videos from a wide range of other sources, with the click of a few buttons.
Magento 2 Youtube Video
Magento Youtube Product Video allows you to include video embeds quickly and easily. The process is simple. Enter the Google Developers console to copy the Data API from Youtube. Next, go into Magento Admin, Stores – Settings – Configuration.
Finally, enter the URL, add a description and title, and voila! The video has been embedded in the site.
In most cases, this will work with no other adjustments. However, you may want to check the frame rate of the original and the embed. You’ll get a higher quality video if the frame rates match. Keeping the resolution in mind is important. It’s best to use a 16:9 resolution with 1080p or 720p. MP4 videos often work best when they are encoded with H.264. Other file formats will work as well, but these will give the most immediate results and no hassles
Vimeo Videos and Other Video Hosting Platforms
To embed a Vimeo video, simply follow the same process as described above for Youtube videos. Regardless of the video source, Magento allows you to customize thumbnail images for all uploads and embeds. It also offers another powerful feature: several embeds can be loaded onto a single products page in a video gallery.
Video galleries can be designed with grid panel, strip panel, and slider options. Each of these designs can be customized. You can select from multiple scrolling options, transition times and durations, and panel background colors, among loads of other features. Other video hosts will work with Magento video extension, in the same way, making it a breeze to embed any video you like to your site.
Magento 2 Self-Hosted Videos
With Magento video tools, you can also embed self-hosted videos on your eCommerce site. However, since these videos often come in a range of resolutions and file formats, you will need to use a video converter to optimize them.
A video converter lets you adjust the format and settings of the video so that the embed works best with Magento. Remember that playing a video use bandwidths. Low bandwidth can reduce the video quality and presentation on your site. To keep it as high as possible, it may be necessary to lower the bitrate of your embed. It may also be necessary to make some compromises with regard to quality.
To use self-hosted videos, you’ll first need to find a quality video converter that supports your desired video format. According to TechRadar, the best free online video converter for 2018 is Apowersoft Free Online Video Converter. To obtain this, simply go to the Apowersoft site. Download a launcher plugin and install it onto your desktop. Once this is done, the video converter can be operated completely through your browser. Apowersoft accepts nearly all video file formats and is capable of providing almost any output formats. Plus, once the file is converted, it can be downloaded or uploaded to a site with no more than a few clicks.
Magento 2 Features to Sell Products Successfully
Magento® 2 is a one-stop-shop to create the store of your dreams. You can use Magento 2 key features to sell more products with your eCommerce store. These Magento 2 features will help you generate leads and conversions so that your store performs its best. For a detailed guide about the best features to sell products, read below!
Magento 2 Feature List to Sell Products
Now we can get into Magento 2 best features. These will help you to sell more products so that you create the best store possible.
Magento Content Management
Magento 2 allows you to manage your content with ease and precision. When you begin an eCommerce store, you’ll always be at a slight disadvantage. That’s because potential customers aren’t able to feel or see the product with their own eyes; as such, you should make sure your products inform your customers about why do they need them and what are the advantages of these products for buyers, and you should make sure that they sell themselves.
You can easily do this with Magento 2 because you can optimize your products and edit them however you see fit. Merchants can create detailed product descriptions; thereby, improving your overall SEO and ranking higher on Google.title=”Magento 2 Marketing Features: How to Attract Potential Customers ” link=”https://web4pro.net/blog-news/magento-2-marketing-features/”
Useful for you:
Magento Omnichannel
Simply put, your customers are more likely to stay with you if you run an Omnichannel store. That’s because they have more variety and control over their orders. When you allow your customers to shop online and pick up their orders in the store, they’re likely to buy 30-40 percent more!
Having an Omnichannel eCommerce business allows you to stay in the competition. That’s because IDC believes that around 50% of retailers will see a profit increase of 30%. This is because, at this time, companies are expecting to have higher revenue.
You can decide to grow your business by creating more flexible orders and by turning your partners into centers of distribution. With this method, you’re able to run your business(es) from the same dashboard.
Magento 2 is built around the idea of being an Omnichannel platform. With Magento 2, merchants are able to create services that work for laptops, mobile devices, and tablets alike.
Useful for you:
Instant Purchase Checkout
By using Instant Purchase Checkout, you can ensure that your customers are able to buy their products quickly and efficiently. Your potential customers likely enjoy the ease of shopping online compared to shopping in a store.
When you use Instant Purchase Checkout in your store, potential customers have less time to debate whether they should buy something; instead, they can click right away to purchase the items in their carts.
Magento 2 Featured Product
Using featured products on a website is a great way to make your eCommerce business to look sleek and efficient. You can show your most popular products on the front page so that they’re more likely to be sold. You can also decide to showcase your least popular products so that they get more exposure.
Featured products show specific items to your customers so if they’re interested, they can click right away and add them to a cart. This can be done right from the front page and your feature can be formatted however you need.
Whether you want to have your feature products appear in a grid or in a slider, Magento 2 has everything you need to get started!
Newsletter Management
Newsletters allow you to keep your customers up-to-date with your business. By using Magento 2’s various Newsletter management features, you can remind customers about your store, which may entice them to buy from you.
Here is what you can do with newsletters:
- the best way to start your newsletters is to have people subscribe to your emails,
- sending emails to your customers and schedule them, weekly, biweekly, or monthly;
- remind customers about their abandoned carts,
- showcase your top products and others that might not be popular, but with the right email structure and buttons with links to the store, they will go out of stock in minutes.
When you compare product in Magento 2, you’ll find that companies with newsletters tend to sell more because it increases exposure to customers.
Promotions
Magento 2 provides you with the opportunity to give promotions to your customers. At the end of the day, everyone loves a discount or sale, and this is one of the best ways to attract people to your business.
You can use various Magento 2 features to offer your customers various discounts and coupons. You can create pricing rules to set promotions or create coupons for specific stores, customer segments, time periods, products, and categories. Merchants can manage all of these coupons from Magento 2’s omnichannel platform and can even receive reports based on these coupons.
In Enterprise edition you can personalize shopping experience with targeting your customers into groups and offering them various discounts, shipping options (i.e. free shipping, fixed amount, etc). Set automated reminders and combine the power of email marketing and offers.
Shipping
This is one of the most overlooked aspects of eCommerce. Your clients depend on getting their products in on time, and they want to do so without having to pay extra.
eCommerce stores are more likely to sell when they price items slightly higher with free shipping compared to providing them with lower product prices and higher shipping costs. That’s why Magento 2 offers merchants a number of shipping options for their stores.
With Magento, you can use the following shipping methods and features.
UPS. Merchants can open an account with UPS to ensure that international orders are placed on time and arrive when they’re expected.
USPS. USPS is an independent U.S. agency that allows eCommerce business owners to ship packages across the United States.
Royal Mail. This is the perfect mailing service for merchants in the United Kingdom because you can ship packages worldwide from your own home.
DHL. This company is based in Germany and is perfect for companies that need international shipping from their business.
FedEx. FedEx can deliver packages from 9 AM to 8 PM from Monday to Sunday. Magento 2 allows you to incorporate this into your store.
International shipping. International shipping is useful for anyone who wants to expand their reach because products and services can be shipped to anyone.
Free shipping. Many customers are willing to pay more for a product if the overall order has free shipping, which makes it ideal for stores that want to increase sales.
Free shipping labels. Shipping labels allow customers to track their shipments, which is a very in-demand feature. Customers want to know how far away their products are so that they can ensure that someone is home to receive the package when it’s supposed to arrive.