Subscribe to خوراک اینچو - آموزش مجنتو
Magento Design and Magento Development Professionals - Inchoo
به‌روز شده: 1 روز 13 ساعت پیش

Magento 2 with Slick Carousel

د., 08/14/2017 - 16:03

Slick is a great Carousel plugin good for any product list like Most Popular, Featured, Upsell, Cross sell products, or any other custom product list. I will guide you with step by step on how to add Slick Carousel and apply it on product list widget on Homepage.

Lets get started!

Installing Slick
  1. Slick. Version in time of writing this tutorial is 1.6.0.
  2. Unzip downloaded folder and copy slick.min.js to app/design/frontend/_YOUR_VENDOR_/_YOUR_THEME_/web/js/
  3. Create or edit requirejs-config.js file in app/design/frontend/_YOUR_VENDOR_/_YOUR_THEME_/web/
  4. Open requirejs-config.js and copy/paste this code: var config = { paths: { slick: 'js/slick' }, shim: { slick: { deps: ['jquery'] } } };
  5. Create “vendor” folder in app/design/frontend/_YOUR_VENDOR_/_YOUR_THEME_/web/css/source/

    Copy slick.less and slick-theme.less into it.

  6. Clear cache and deploy files
  7. Open frontend, view source code and find in <head> tag below code <script type="text/javascript" src="http://_YOURDOMAIN_/pub/static/_VERSION_/_requirejs/frontend/_YOUR_VENDOR_/_YOUR_THEME_/en_US/requirejs-config.js"></script>

    In the bottom of the document you should see a code we added in step 4.

Apply Slick to product list widget

It below steps, we will initialise Slick to product list widget template file.

  1. Create “Magento_CatalogWidget” folder in the root of your theme and copy below folder in it. vendor/magento/module-catalog-widget/view/frontend/templates
  2. Open app/design/frontend/_YOUR_VENDOR_/YOUR_THEME/Magento_CatalogWidget/templates/product/widget/content/grid.phtml
  3. Initialise Slick Carousel before closing <?php endif; ?> with example code below <script> require([ 'jquery', 'slick' ], function ($) { jQuery(document).ready(function () { jQuery(".widget-product-grid").slick({ dots: true, infinite: true, speed: 300, slidesToShow: 4, slidesToScroll: 4, responsive: [ { breakpoint: 1280, settings: { slidesToShow: 3, slidesToScroll: 3 } }, { breakpoint: 768, settings: { slidesToShow: 2, slidesToScroll: 2 } }, { breakpoint: 600, settings: { slidesToShow: 1, slidesToScroll: 1 } } ] }); }); }); </script>
Create and insert product list widget in Homepage
  1. Open Magento Admin → Content → Pages → Home Page
  2. Content → Show/Hide Editor → Insert Widget → Widget Type(Catalog Products List) → Populate fields and choose Conditions (choose category you want or products for example)
  3. Save widget & save page
  4. Check your Homepage and you should have Slick carousel for product list widget
  5. Last step is to customise Slicks CSS for your needs!

Thanks for reading!

The post Magento 2 with Slick Carousel appeared first on Inchoo.

Adding custom entries to admin system configuration

س., 08/01/2017 - 15:53

Hello, in this article we will cover how to add custom entries in existing system configuration located in Stores->Configuration.
We have already covered how to create Magento2 module, so here we will go straight to the point. Replace Inchoo/Test from entries in this article to your module name.

in etc/adminhtml/system.xml inside your module add the following entries:

<config xmlns:xsi="" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Config:etc/system_file.xs <system> <tab id="inchoo_custom_config" translate="label" sortOrder="100"> <label>Inchoo Custom Config Page</label> </tab> <section id="inchoo_entry_1" translate="label" sortOrder="100" showInDefault="1" showInWebsite="1" showInStore="1"> <class>separator-top</class> <label>Inchoo Config SubItem</label> <tab>inchoo_custom_config</tab> <resource>Inchoo_Test::config</resource> <group id="general" translate="label" sortOrder="10" showInDefault="1" showInWebsite="0" showInStore="0"> <label>General Configuration</label> <comment>This is example configuration page.</comment> <field id="inchoo_text" translate="label" sortOrder="1" showInDefault="1" showInWebsite="0" showInStore="0"> <label>Text</label> <comment>This is example comment.</comment> </field> <field id="inchoo_yesno" translate="label" type="select" sortOrder="10" showInDefault="1" showInWebsite="0" showInStore="0"> <label>Is Enabled</label> <source_model>Magento\Config\Model\Config\Source\Yesno</source_model> </field> <field id="inchoo_dropdown_custom" translate="label" type="select" sortOrder="20" showInDefault="1" showInWebsite="1" showInStore="1"> <label>Inchoo Custom Dropdown</label> <source_model>Inchoo\Test\Model\Config\Custom</source_model> </field> <field id="inchoo_dropdown_dependable" translate="label" type="select" sortOrder="30" showInDefault="1" showInWebsite="1" showInStore="1"> <label>Inchoo Custom Dependable Dropdown</label> <depends> <field id="*/*/inchoo_yesno">1</field> </depends> <source_model>Inchoo\Test\Model\Config\Custom</source_model> </field> <field id="inchoo_multiselect" translate="label" type="multiselect" sortOrder="40" showInDefault="1" showInWebsite="0" showInStore="0" canRestore="1"> <label>Multiselect</label> <source_model>Inchoo\Test\Model\Config\Multiselect</source_model> </field> </group> </section> </system> </config>

Text entry

First field id=”inchoo_text” is a simple text field that will work simply by defining it in system.xml and does not require any source models.

Yesno entry

Field id=”inchoo_yesno” is classic yes/no dropdown as from Magento 1. Besides defining it in system.xml, no additional work is required for it to work.

In order for certain custom areas to work, we have to define source models stated in our system.xml. Although Magento will handle most of the work, we have to cover labels or logic (if needed) for our custom outputs.

Custom dropdown

For custom dropdown defined under id=”inchoo_dropdown_custom” we will add custom source model Inchoo\Test\Model\Config\Custom:

<?php namespace Inchoo\Test\Model\Config;   class Custom implements \Magento\Framework\Option\ArrayInterface { /** * @return array */ public function toOptionArray() { return [ ['value' => 0, 'label' => __('First')], ['value' => 1, 'label' => __('Second')], ['value' => 2, 'label' => __('Third')], ['value' => 3, 'label' => __('Fourth')] ]; } }

Depends tag

Next example id=”inchoo_dropdown_dependable” is the same as last one, but because we added depends tags in system.xml it will depend strictly on value of inchoo_yesno. This is part of system.xml that makes it dependable:

<depends> <field id="*/*/inchoo_yesno">1</field> </depends>

Custom Multiselect

In order to make custom multiselect id=”inchoo_multiselect” to work, we first have to define source model Inchoo\Test\Model\Config\Multiselect like this:

<php namespace Inchoo\Test\Model\Config;   class Multiselect extends \Magento\Captcha\Model\Config\Form\AbstractForm { /** * @var string */ protected $_configPath = 'inchoo/multiselect';   /** * Returns options for form multiselect * * @return array */ public function toOptionArray() { $optionArray = []; $backendConfig = $this->_config->getValue($this->_configPath, 'default'); if ($backendConfig) { foreach ($backendConfig as $formName => $formConfig) { if (!empty($formConfig['label'])) { $optionArray[] = ['label' => $formConfig['label'], 'value' => $formName]; } } } return $optionArray; } }

Next step is to define default multiselect values. Inside etc/config.xml add the following entries that will represent default values, also notice that config tree is made from string defined inside protected variable $_configPath defined earlier in Inchoo\Test\Model\Config\Multiselect:

<config> <default> <inchoo> <multiselect> <first_entry> <label>First entry</label> </first_entry> <second_entry> <label>Second entry</label> </second_entry> </multiselect> </inchoo> </default> </config>

This is it, just make sure to flush cache and refresh. Enjoy!

The post Adding custom entries to admin system configuration appeared first on Inchoo.

Importance of style guides in design

پ., 07/27/2017 - 12:37

One may call it Graphics Standard Manual, Identity Style Guide, Brand and Graphics Manual, Branding Manual, Brand book… People call it differently, but they all usually mean the same thing (although we should be careful about using “brand” in naming, cause brand books/manuals dictate not only visual and graphic representation, but the brand as a whole).

We’re basically talking about a set of standards and rules by which we enforce a certain style to be applied on company’s documents, presentations, visuals like posters and flyers, communication strategies or even photos.

It can be as broad as it needs to be to everything we may need to use, but keep a recognizable company style by using the same typography, colors, logos etc.

Web style guide is also a set of standards and rules, but meant to be applied throughout your website to ensure consistency and cohesive experience. It can be a part of a company style guide dictating how the brand will be presented on a website, but on the other hand it can be an independent document. For instance, if you only do business online and don’t have that much need for anything “offline”, your web style guide can double as your company style guide (you can easily make your business cards based on your web style guide), or be a good place to build upon if you’re thinking of creating one.

So how do we build a web style guide?

Most of the businesses already have some styles defined. It may be a whole set of standards, but it may also be just a logo and a few colors. This is often a good place to start. We’ll go through your existing documentation and take everything we need and can use to keep things within your existing style framework. We’ll never try to change your style (unless of course you ask as to). If you’re coming empty handed, we’ll have to research your brand in order to define what would best suit your needs and start from there.

COLOR is a logical place to start building! If your company hasn’t already defined some colors to be used, we’ll turn to your logo for help, because you’ve probably incorporated your “brand color” into it. Now that we have your “primary color”, we’ll turn to the humanity’s best invention ever. The Wheel. More precise – the color wheel. There are a few standard color harmonies (complementary, analog, triadic…) we can turn to when combining colors. 2-3 colors are usually enough, given that we’ll use a few shades of every, depending on the content so we’ll have enough to work with.

It’s important to know that some colors may need a bit of tweaking for displaying them on screens. If a color looks good on some other medium, it won’t necessarily be true for displays (and the other way around). There’s nothing strange in using two shades of the same color for web and for print. So if we offer you a slightly updated brand color, don’t dismiss it right away. There’s probably a good reason we did it. Not to mention that different displays will display the same color – differently. So brightness and saturation are something we must keep in mind.

Now that we have a nice set of colors it’s time to move on.

TYPOGRAPHY, or 95% of your website according to some, the most important part of your website and must not be taken lightly. Picking the right font face for any medium can be tricky. We have two options – go for fonts we know will do the job right, or “go into the wild” and experiment with fonts and font pairing. This usually depends on the type of business we’re working on. One can’t just use the same font face for a fashion store, veterinary store, and a flower shop. Typography should reflect your business.

When choosing a font, we also have to be careful and have a set of “fallback”, replacement fonts. Those are fonts that browser will use if the primary font is not loaded for some reason. In such scenario we want to keep everything nice and tidy, so choosing a proper fallback font is also important.

Once we have found you a perfect type face, it’s time to make a typography scale. We’ll define all text styles for headings and body texts and establish a clear hierarchy between them. These styles will be used throughout your website.

This is a crucial moment. Once we’re deep in a project, it’s hard to go back and change the type, because changing only one font size may result in a need to change all other sizes in order to retain a type hierarchy. This may come as a simple variable change in a CSS preprocessor,  but this is very hard in a graphics software, because graphics software doesn’t do variables. While changing a type in CSS will keep all paddings and margins in order, for us, other than changing the font size and line height, this means adjusting all margins and paddings around every piece of text “by hand”.

This is why sometimes it may be hard to “make that title a tad smaller” – because that title is a shared style used on other ten pages, and that style is interconnected with other styles through a typography scale.

Now that we have our two basic elements, we can create some more basic elements. We’ll do some primary and secondary BUTTONS, start assembling ICONOGRAPHY and perhaps wrap it all up with some FORMS.

Although there’s lots to tell about the last three (and of course, it doesn’t stop there) we’ll keep it short and not go into details of their how and why. What’s important is that every other element we create consist of color, typography or both, so with these two basic building blocks we cover a lot of grounds and have the primary ingredients to build every other element we may need.

So to recap – we’ve defined colors and type scale, drawn some buttons, put together some forms and now what?

Well, now it’s time to start building using elements defined in style guide. And this is the importance of having (and following) a style guide. By following our style guide we are now sure to be using the right typeface with the right font sizes for all intended purposes. We have consistent buttons with same color, shadow and border radius throughout the store, all our form labels are always at the same location in regards to text boxes, our shadows are always going from left to right, we’re not choosing a color of navigation bar with a color picker based on our feeling or current mood…

We now have and follow STANDARDS.

What’s important to realize is that the style guides are not closed systems. They’re designers playground and they’re regularly updated. While designing, we often find ourselves in need of something not (yet) covered by the style guide. Somewhere along, maybe we decide to give all buttons a nice lightly transparent black shadow but hadn’t defined any shadow style before. This is the time to add that shadow style to our style guide so next time we need a shadow – we use the same. Later if we change our minds about the shadow and make it for instance orange – it’s important to change the color in style guide as well, so we always have a consistency and uniformity.

This was just an overview of the most basic style guide imaginable. Sort of a “starting point” to have something we can work with and build upon. By the end of the project style guide goes through series of changes and may also include things like layouts, design patterns, grids, interactions, animation, setting the tone or voice for copy, determine imagery and overlaying text on an image. We can standardize pretty much anything and go into tiniest details if see needed. All with the aim of having a clear standardization to follow and to ensure consistent and cohesive experience.

The post Importance of style guides in design appeared first on Inchoo.

Why you should do keyword research for your eCommerce store

پ., 07/20/2017 - 15:29

Every time someone does a search for something on search engines such as Google, the search engine must go through thousands of pages and serve the best results that will give the user most useful information he searched for.

How does the search engine know what information to serve based on just a few words?  Well, search engines use to determine the best and most relevant information for every search term that is entered on search engine from user. Because of that, it is very important to create a strategy of keywords so that your eCommerce store could rank better every time user search for terms that are related to products that you sell. The ultimate goal is to rank on the first page of search engine and make your eCommerce more visible to users.

For that matter, it is very important that you know what keywords to include on your site and to do thorough research of words you think could trigger your store higher on search results.

Keyword research is a strategy used by SEO experts to find alternative search terms people are entering into search engines while looking for a specific subject. They then collect those keywords and create a strategy to achieve better rankings on search engines. It then helps them to better understand terminology that your potential customers are searching to find products you’re selling.

If you can improve your skills about keyword research strategy for your business, you will certainly benefit from more search engine traffic and also know your customers better than your competition.

In this article, we will cover the basic terms you must know about keyword research for eCommerce to help search engines to understand what is your site about and what are you selling, and help you to rank better and increase your sales.

Basic Terms for Keyword Research


Keywords are search terms that millions of people enter into search engines while looking and searching for a specific information. Google tracks all of this information and also offers you a few tools to use to improve your strategy of keyword research. Keywords are here to explain what your web site is about and you want keywords on your store to be relevant to what people are searching for.

Long Tail Keywords

Long tail keywords are more specific keywords people are searching for on search engines, and they contain three or more than three words. They are more specific than keywords that contain one or two words, because in this case, the user is searching for a specific query. Someone who is searching for a „red dress“ is probably just collecting information and exploring, but someone who enters „little red cocktail dress for prom price“ is much closer to purchasing the product. It is better to concentrate on those people who are searching for a specific product because they probably already researched about it and are ready to buy it.

Search Volume (Avg. Monthly Searches)

Search volume is the number of searches that are shown for a specific keyword within a certain period of time. It would be ideal if you could look for the keywords with the highest search volume because it means more potential traffic and conversions on your eCommerce store.


Maybe the most important segment of keyword research is keyword competition. It measures how difficult it will be to rank for a specific keyword on search engines. It depends on how popular is the search term or the industry that is related to the search term. It would be ideal if your keywords have high search volume and low competition, but those kind of  keywords are very difficult to find and require a lot of work that will certainly pay off, so when you see a ton of keywords when making a plan, don’t panic, be smart and start making a list.

Use Keyword Planner

Real keyword research cannot be done properly without a keyword planner tool.  Keyword planner tool is here to help you discover completely new concepts and terminology that users use to find what they are looking for, and that maybe didn’t occur to you. It gives you the option to make a list for every group of similar keywords that you could split by categories on your store. Statistics like search volume of a specific keyword could help you decide which keywords you could use on your site on the specific page.

Make  a List of Keywords

As I mentioned before, after seeing hundreds of words listed on your keyword planner tool when you search for queries you think that would your future customer’s search, don’t panic, rather be wise and make a list that will contain similar search terms and make it easy to manage your future strategy.

For example, if you have a category page for certain brand on your store for women, you can make list for every subcategory page of your store that will contain keywords related to that subcategory.

Let’s make is simple. You have category for Women’s clothes. It contains five subcategories:

  • Bags & Purses
  • Coats & Jackets
  • Tracksuits
  • Sweatshirts
  • Accessories

For every subcategory listed above, you will make a special list that contains keywords related to that specific category. In that case, in subcategory Bags & Purses it is logical to put words such as: bags, women’s bags, purses for women, women’s purses, and so on.

This part of work is very hard and requires full concentration, but in the end, it will definitely pay off with higher rankings of your store and result in more conversions.


Although I know that keyword research demands a lot of work and takes a lot of time, from my experience, it will surely pay off when you implement those keywords on your eCommerce store, from the SEO point of view. Over time it will result in higher page rank, more visitors and for that, more customers, increase of sale and growth of conversions.

If you find this article useful and you want to know more about this, or you want to improve page rank, sales, attract more visitors to your eCommerce store, see what we offer in SEO Audit.

The post Why you should do keyword research for your eCommerce store appeared first on Inchoo.

Validate a custom form in Magento 2

چ., 07/19/2017 - 14:28

This article will cover the fundamentals of validating any form in Magento 2.

The contact form on Contact us page will be used and modified for the purpose of the article. The form itself can be found in the following paths, depending on the type of installation you are using:

  • app/code/Magento/Contact/view/frontend/templates/form.phtml
  • vendor/magento/module-contact/view/frontend/templates/form.phtml

In order to demonstrate how to get the forms to be validated, let’s create a validation-free form with some fields. Copy the file from one of the paths above and paste it into your theme:

  • app/code/VENDOR/THEME/Magento_Contact/frontend/templates/form.phtml

Next, paste the following code inside of it:

<form class="form contact-inchoo" action="<?php /* @escapeNotVerified */ echo $block->getFormAction(); ?>" id="contact-form" method="post" data-hasrequired="* Required Fields"> <fieldset class="fieldset"> <div class="field name required"> <label class="label" for="field1"><span>Field 1 (using data-validate)</span></label> <div class="control"> <input name="field1" id="field1" title="Field 1" value="" class="input-text" type="text" /> </div> </div> <div class="field name required"> <label class="label" for="field2"><span>Field 2 (using attribute)</span></label> <div class="control"> <input name="field2" id="field2" title="Field 2" value="" class="input-text" type="text" /> </div> </div> <div class="field name required"> <label class="label" for="field3"><span>Field 3 (using classname)</span></label> <div class="control"> <input name="field3" id="field3" title="Field 2" value="" type="text" class="input-text" /> </div> </div> <div class="field name required"> <label class="label" for="field4"><span>Field 4 (using data-mage-init)</span></label> <div class="control"> <input name="field4" id="field4" title="Field 4" value="" class="input-text" type="text" /> </div> </div> <?php echo $block->getChildHtml(''); ?> </fieldset> <div class="actions-toolbar"> <div class="primary"> <input type="hidden" name="hideit" id="hideit" value="" /> <button type="submit" title="Submit" class="action submit primary"> <span>Submit</span> </button> </div> </div> </form>

Your form should look like this one:

If you click the “Submit” button, the form would be submitted.

Step 1: add the validation component

Add this attribute on the form tag:


This one data attribute tells Magento that the form must be validated before submit and that  validation alias should invoke some particular file using RequireJS. If you take a look at the page source of the compiled file RequireJS config file (found in pub/static/frontend/VENDOR/THEME/LOCALE/requirejs-config.json), you should be able to find the following snippet:

var config = { map: { "*": { ... "validation": "mage/validation/validation", ... } } ... };

The string on the right of the validation alias matches the lib/web/mage/validation/validation.js file that will load entire validation logic and take care of your input fields.

Step 2: add some validation rules to your input fields

By looking at the code of validation logic, Magento made it possible to set validation rule names by using one of the following methods listed here:

  1. method #1 – by setting data-validate attribute on the input field: <input data-validate='{"required":true}'name="field1" id="field1" ... />
  2. method #2 – by setting the rule names as attributes: <input required="true" name="field2" id="field2" ... />
  3. method #3 – by setting the rule names as classnames: <input class="input-text required" name="field3" id="field3" ... />
  4. method #4 – by setting the rules inside of the data-mage-init attribute on the form tag <form ... data-mage-init='{ "validation":{ "rules": { "field4": { "required":true } } } }'>

Now when you submit your form, all of the fields should be invalid, like on the image:

Rules with arguments

If you have to use a rule that requires a parameter (for example, minlength, maxlength and many other) you can use one of the following three methods, which ever you prefer:

  • method #1 data-validate='{ "required":true, "minlength":10 }'
  • method #2 required="true" minlength="15"
  • method #4 – you have to manually specify name attribute of each input field which rules are applied (which is already taken care of if you use it inline with data-validate attribute) data-mage-init='{ "validation":{ "rules": { "field4": { "required":true, "minlength":20 } } } }'
List of form validation rules

To wrap up this article, a list of validation rule names is provided here as a quick reference toward the official documentation:

  1. jQuery rules:
    1. required,
    2. remote,
    3. email,
    4. url,
    5. date,
    6. dateISO,
    7. number,
    8. digits,
    9. creditcard,
    10. equalTo,
    11. maxlength,
    12. minlength,
    13. rangelength,
    14. range,
    15. max,
    16. min
  2. Magento rules:
    1. max-words
    2. min-words
    3. range-words
    4. letters-with-basic-punc
    5. alphanumeric
    6. letters-only
    7. no-whitespace
    8. zip-range
    9. integer
    10. vinUS
    11. dateITA
    12. dateNL
    13. time
    14. time12h
    15. phoneUS
    16. phoneUK
    17. mobileUK
    18. stripped-min-length
    19. email2
    20. url2
    21. credit-card-types
    22. ipv4
    23. ipv6
    24. pattern
    25. allow-container-className
    26. validate-no-html-tags
    27. validate-select
    28. validate-no-empty
    29. validate-alphanum-with-spaces
    30. validate-data
    31. validate-street
    32. validate-phoneStrict
    33. validate-phoneLax
    34. validate-fax
    35. validate-email
    36. validate-emailSender
    37. validate-password
    38. validate-admin-password
    39. validate-customer-password
    40. validate-url
    41. validate-clean-url
    42. validate-xml-identifier
    43. validate-ssn
    44. validate-zip-us
    45. validate-date-au
    46. validate-currency-dollar
    47. validate-not-negative-number
    48. validate-zero-or-greater
    49. validate-greater-than-zero
    50. validate-css-length
    51. validate-number
    52. required-number
    53. validate-number-range
    54. validate-digits
    55. validate-digits-range
    56. validate-range
    57. validate-alpha
    58. validate-code
    59. validate-alphanum
    60. validate-date
    61. validate-date-range
    62. validate-cpassword
    63. validate-identifier
    64. validate-zip-international
    65. validate-one-required
    66. validate-state
    67. required-file
    68. validate-ajax-error
    69. validate-optional-datetime
    70. validate-required-datetime
    71. validate-one-required-by-name
    72. less-than-equals-to
    73. greater-than-equals-to
    74. validate-emails
    75. validate-cc-type-select
    76. validate-cc-number
    77. validate-cc-type
    78. validate-cc-exp
    79. validate-cc-cvn
    80. validate-cc-ukss
    81. validate-length
    82. required-entry
    83. not-negative-amount
    84. validate-per-page-value-list
    85. validate-per-page-value
    86. validate-new-password
    87. required-if-not-specified
    88. required-if-all-sku-empty-and-file-not-loaded
    89. required-if-specified
    90. required-number-if-specified
    91. datetime-validation
    92. required-text-swatch-entry
    93. required-visual-swatch-entry
    94. required-dropdown-attribute-entry
    95. Validate-item-quantity
    96. validate-grouped-qty
    97. validate-one-checkbox-required-by-name
    98. validate-date-between
    99. validate-dob

Congratulations, you have reached the end of this article! If you have any questions, feel free to post a comment below.

The post Validate a custom form in Magento 2 appeared first on Inchoo.

CSS Media queries in Magento 2

س., 07/11/2017 - 16:24

It’s highly unlikely that there are some frontend developers involved in a responsive website development who are not familiar with the concept of CSS Media queries. In this post, I’ll be looking at Magento 2 way of implementing this functionality in its default theme development workflow.

How do Magento 2 media queries work?

In the heart of Magento 2 media queries mechanism, defined in Magento UI library, is a .media-width() mixin.

.media-width(<@extremum>, <@break>);

@extremum: max|min – sets whether to use min-width or max-width in media query condition

@break: value – sets the value of breakpoint to compare with in media query condition

We can see the practical use of it in the following example:

// In .less file .media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__s) { your styles }   // After compilation, in .css file @media only screen and (max-width: 640px) { your styles }

This mixin, which is used for grouping style rules in certain media queries, can be used whenever you need it, in any .less file in your theme. In the end, it will be invoked only once – in lib/web/css/source/lib/_responsive.less file.

If you check the end product of .less files compilation, styles.css file, you’ll see there each media query with all its rules only once, so there are no a multiple calls for the same query.

Default settings

By default, media queries are outputting styles in two different files:

1. styles-m.less – which generates basic and mobile-specific styles

2. styles-l.less – generates desktop-specific styles (for 768px width screen and higher)

This means that, when the website is opened on a mobile device, it will load only styles compiled from the styles-m.less file. Extra styles from the second file (styles-l.less) are compiling and loading only if the screen width is 768px or higher.

For this style groups separation, special variables @media-target and @media-common are used:

// For targetting device for styles output @media-target: all|desktop|mobile   // In practice & when (@media-target = 'mobile'), (@media-target = 'all') { @media only screen and (max-width: (@screen__xs - 1)) { .media-width('max', @screen__xs); } }   // For deciding whether to output common styles. @media-common: true|false   // Adding common styles & when (@media-common = true) { your styles }

Out of the box, Magento UI library has a set of predefined variables for breakpoints. We can use them in any case we need them and they can be changed or extended them with a new ones:

  • 320px
  • 480px
  • 640px
  • 768px (breakpoint for switching between mobile and desktop views)
  • 1024px
  • 1440px
Custom breakpoints

Quite often, we’ll find ourselves in a situation where we’ll need to add an additional breakpoint (apart from default ones) in which we can apply a different styling. There are three things which need to be done in order to add a custom breakpoint in our theme.

1. Define a variable for the new breakpoint.

First, we’ll have to create a /web/css/source/variables.less file. If we would use a standalone theme, this file would be new and empty. But, since we’re following the best practice (inheriting from Magento Blank theme), we’ll have to copy this file from our parent theme.

Here we can define our custom breakpoint:

@custom__breakpoint: 1280px; 2. Implement our new breakpoint

To do so, we’ll override _responsive.less file from Magento UI library by copying it to our theme in /web/css/source/lib/. Now, in our theme’s _responsive.less file we have to edit .media-width() mixin by adding the appropriate rule for the new custom breakpoint.

& when (@media-target = 'desktop'), (@media-target = 'all') { @media all and (min-width: @custom__breakpoint) { .media-width('min', @custom__breakpoint); } } 3. Implement the screen changes for the new breakpoint.

If everything is set properly, we should be able call our new .media-width() mixin whenever we need it in our theme .less files.

.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @custom__breakpoint) { // Stlying applied at @custom__breakpoint breakpoint } A small helper

In the end, to wrap things up, I’ll give you some quick jump-start piece of code; media queries which you can quickly apply, depending on which screen size you’d like to target.

// Common // (for styles used in both mobile and desktop views) & when (@media-common = true) {}   // Mobile // (for all mobile styles.) .media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__m) {}   // Tablet .media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) {   // Desktop .media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__l) {}

Thank you for reading!

The post CSS Media queries in Magento 2 appeared first on Inchoo.

Adding videos to product page in Magento2

د., 07/10/2017 - 13:08

Today is even impossible to imagine a good product detail page without product video/s. In Magento 2, adding videos to the product details page is quite easy. The major problem is in most cases with an initial setup. Most of the product videos already exist online, either on or In the first case, it’s the most popular video publishing platform and for we can say it is more or less dedicated to professionals and photo/video enthusiast.

Google, company behind youtube, set few rules regarding sharing and embedding videos to other domains, in our case our online store. They require to have enabled youtube API key if you want to use embedding youtube videos beyond simple grabbing embed code from youtube videos page.

  • In Magneto 2 first step is to configure youtube API key under settings. So first we go and enable google API key for youtube videos.

  • You will get a window with option to create new project or you can add it to existing if you have already created project with google API.

    Create new project

  • You will need to fill up few basic information:

    Project basic information

  • After hit on Create button you will have option to generate API key:

    Create API key

    Select API key

  • Please note here is one important option to consider, Restrict key, please go with this option and restrict usage of this key only to specific domain. You can update API key name, restrict only to specific domain which you can add at the bottom. Hit save.

    Restrict key to domain

  • Ok, great we have now API key. But we need to enable it :-). Go to select in left menu Dashboard and click Enable API

    Enable API

  • Next thing is to select service, in our case it is Youtube:

    Youtube API

  • Now the final step is to enable and run API:

    Enable API

  • At the end, you will get dashboard with all information regarding API usage, and also you can disable API:

    Youtube API dashboard

  • Next thing is to login in Magento 2 admin. Go to Store -> Configuration -> Catalog -> Catalog -> Product Video.

    Add video API Magento

    Paste your API key here, hit save. Please note there are few additional options in general. You can set if the video is base (switching order of gallery images and set to video be first one in line) it will autoplay, after video is finished load related videos, replay video. We will keep it on NO. Save and clear cache.

  • Next step is to open product for which we have video. Scroll down to Images and videos, click Add Videos.

    Add Video

  • Next you will copy paste youtube URL, all other data will be populated automatic.

    Information about video

  • Please update Image preview role, it can be base, small etc.

    Image preview role

  • Save and you will have video inside media gallery collection.

    Media Gallery

  • Save product and go to product detail page on frontend.

    Category page listing

  • On product detail page we will have image thumbnail for video, click play and there you go.

    Product detail video

As for vimeo video things are simpler. Just paste video URL, edit description and hit save.

I hope this short walkthrough will help you to master adding and editing Magento 2 media gallery, adding new media rich content to product details page.

The post Adding videos to product page in Magento2 appeared first on Inchoo.

Override Magento 2 Layout: Product page example

پ., 07/06/2017 - 15:30

Layouts play a major roll in Magento. This roll is well known from Magento 1x layout approach. With Magento 2 couple of things are changed and improved. Really, we finally have on our disposal useful layout manipulation options.

Layout basics

If you are here just for example and you already familiar with Magento 2 Layout, skip it this section.

Layout is a page structure, represented by elements hierarchy, which can be: blocks and containers.
Technically, layout is defined in the .xml files. Files which contain element declarations and different manipulation instructions.

Module and theme layout files

Magento 2 layouts are provided by different application components. We can split them in two major groups Base layout and Theme layout. Let us mention main difference between them.

Base layouts

This Layout files are provided by modules. We can find page configuration and generic layout files on this path:

And page layout files on path:

The main file of Base layout, if you wish to check it, is located on path:

Theme layouts

Theme layouts are logical files provided by Magento themes. Here we can find page configuration and generic layout files. Check them on path:

Also, the page layout files are on path:

Override a layout

Above mentioned basic are necessary in order to understand how to properly override Magento 2 layout. The layout needs to be properly overridden when we perform some kind of customization, for example when we:

  • Modify method arguments
  • Remove blocks and/or containers
  • Set up XML attributes of blocks and containers
  • Remove block arguments
  • Modify and suppressing handles inclusion
  • Remove all handle instructions by declaring an overriding layout file with an empty handle
Override base layouts

To override base layout file (layout provided by the module) we need to put a layout file with the same name in the following location:

These file override the following layout:

Override theme layouts

To overriding theme layout (override a parent theme layout) put a layout file with the same name in the following location:

These files override the following layouts:
To override page layout files, use ‘page_layout’ directory name instead of ‘layout’.

Product page override

Now when we are familiar with layout overriding rules, let’s make a real life example. Let’s override product page layout.

Overriding product page for specific products

For example, our client has two or more types of products and on top of that, client also has one special product which is totally different. So client also wishes to present that product in different product page. Basically, we need at least three different product page layouts.

Luckily Magento 2 provides this kind of flexibility by using native addPageLayoutHandles method. Mentioned method provides possibilities of overriding layout using:

  • Product ID
  • Product SKU
  • Product TYPE

On top of that, method will also support your custom product type. For instance if we create a product type with the name “inchoo”, you can then create a file called catalog_product_view_type_inchoo.xml to handle specific layouts for this type of products.

So, let start first with overriding layout for just one specific product.

In order to do that we need to follow this steps:

  1. Create new layout file inside our theme scope, the name of layout file will be: catalog_product_view_id_number and we’ll place it in:

    Similar like this:

  2. Override what we need inside of layout file (remove blocks, add new blocks etc.).
  3. Clear Magento’s cache and reload page.

We are preferring to use product ID. But if product ID isn’t good option for you, you can use SKU number for targeting product, in that case your layout file need have name in this form:

Now let’s create unique product page for specific product type. As you probably know Magento by default has few different product types (bundle, configurable, downloadable etc.). So for example, if we wish to have different layout for downloadable products, we need to use corresponding product type name to target that layout.

In order to override downloadable products, follow this steps:

  1. Create new layout catalog_product_view_type_downloadable.xml file inside Magento theme.


  2. Override what we need inside of layout file (remove blocks, add new blocks etc.).
  3. Clear Magento’s cache and reload page.

Same naming principle can be followed for other type of products, like this:


Important note: Current Magento 2 version has bug with configurable product type. Unfortunately it isn’t possible to override configurable products just by creating new catalog_product_view_type_configurable.xml layout file. We hope that the next version of Magento will solve this bug. Stay tuned here.

The example is short but I hope that this article can help you with overriding layouts.

If you have issues on your web store and you need frontend assistance, contanct us for usability audit.


The post Override Magento 2 Layout: Product page example appeared first on Inchoo.

Blogging for merchants: attract visitors to your eCommerce site

س., 06/27/2017 - 18:03

Every store owner knows how important blogging is for his eCommerce. It’s a perfect opportunity to attract a broader audience that might not have a clear buying intent at the moment, but that will certainly come back to you after learning something useful from your blog. However, if your articles are low quality, non-informative and just there to fill out the blank space – you’re not using the full potential of the blog section on your site. To avoid frustration with articles that don’t get any attention, we’re bringing you blogging tips for merchants, that can help you boost your eCommerce website’s online reputation.

1. Tailor your content to your targeted audience

It sounds pretty obvious, right? But it isn’t as easy as it seems. To tailor your content to your targeted audience, the first thing you should do is to explore the needs of your potential audience. Only if you know what they are looking for, you can create content that will attract them to your blog (and additionally to your store). There’s no point in writing articles about the things nobody wants to read about, so it’s necessary to take some time and do a research.

2. Size does (not) matter

It’s easy to get carried away when trying to impress the potential visitors (and buyers), but you should be careful because quantity doesn’t necessarily mean quality. Large articles without consistent theme won’t perform well within your targeted audience, but neither will short articles that don’t bring any valuable information. There’s no magic formula for ideal blog post’s length. The ideal length is the one that covers your theme and gives useful information to your targeted audience. So, focus on quality, write informative articles and stay within a theme.

3. Don’t try to trick your visitors and sell your products via blog post

As easy as it is. Your visitors are smart enough to recognize if you’re trying to trick them by “selling your stuff” as useful information, and they won’t like it. They might never come back to you if every second word in your article is linking to a specific product in your eCommerce store. It’s OK to point them in the right direction and show them something valuable, but don’t be pushy. Be wise, respect your audience and don’t try to trick them.

4. Don’t overstuff your article with keywords

If you’re trying to rank by focusing on keyword density, you’re doing it wrong. Stuffing blog posts with keywords almost necessarily mean creating thin, low-quality content. It’s much more important to focus on providing valuable information to your targeted audience. Google is smart and it can recognize quality content without keyword stuffing. Rank for your quality and your visitors will turn into your customers.

5. Consistency is key to successful blogging

As you could already notice, consistency is very important when it comes to blogging. Don’t give up if the first couple of articles aren’t performing as expected. Stick to your plan, publish regularly and the results will come.

Blogging isn’t an easy task, and it certainly is time-consuming, but the hard work pays off. The results may not come immediately, and not every blog post you write will be successful, but over time you will notice the results and you will know that it was all worth it.

If you’re not certain in which direction should you go, or you need additional advice for improving the SEO of your eCommerce site, don’t worry, our team of consultants can help you. We can create a Custom SEO Audit with the best tips for your online store. Don’t hesitate, start your journey to success now.

The post Blogging for merchants: attract visitors to your eCommerce site appeared first on Inchoo.

Managing My Account Navigation Links in Magento 2

د., 06/26/2017 - 16:12

Looking at the old articles on our website that long for a rewrite, I sometimes stumble upon a gem that can be useful. This is a rewrite of the article originally written for Magento 1 – Managing navigation links in the account dashboard

In this article I’ll demonstrate how to manage navigation links in your customer’s account dashboard.

Step 1

First of all, you need a create customer_account.xml in your theme in:

app/design/frontend/_YOUR_VENDOR_/_YOUR_THEME_/Magento_Customer/layout/customer_account.xml Add a Custom Link

All we need to do is add this code to our layout xml file:

<referenceBlock name="customer_account_navigation"> <block class="Magento\Framework\View\Element\Html\Link\Current" name="customer-account-navigation-custom-link" after="-" > <arguments> <argument name="label" xsi:type="string" translate="true">Custom Link Label</argument> <argument name="path" xsi:type="string">custom-path</argument> </arguments> </block> </referenceBlock> Re-order links <move element="LINK_YOU_WANT_TO_MOVE" destination="customer_account_navigation" AFTER_OR_BEFORE="NEW_POSITION" />   <!-- eg. "My Wish List" move after "My Orders" --> <move element="customer-account-navigation-wish-list-link" destination="customer_account_navigation" after="customer-account-navigation-orders-link" />

We “moved” the element from its original location and placed it back there, at the same time telling M2 to place it after/before link we want.

Remove the link

To shorten and simplify the story, in the example below I will immediately show you how to delete all links from the navigation one by one.

<!-- Store credit --> <referenceBlock name="customer-account-navigation-customer-balance-link" remove="true"/>   <!-- Downloadable product link --> <referenceBlock name="customer-account-navigation-downloadable-products-link" remove="true"/>   <!-- Subscription link --> <referenceBlock name="customer-account-navigation-newsletter-subscriptions-link" remove="true"/>   <!-- Billing agreement link --> <referenceBlock name="customer-account-navigation-billing-agreements-link" remove="true"/>   <!-- Product review link --> <referenceBlock name="customer-account-navigation-product-reviews-link" remove="true"/>   <!-- My credit card link --> <referenceBlock name="customer-account-navigation-my-credit-cards-link" remove="true"/>   <!-- Account link --> <referenceBlock name="customer-account-navigation-account-link" remove="true"/>   <!-- Account edit link --> <referenceBlock name="customer-account-navigation-account-edit-link" remove="true"/>   <!-- Address link --> <referenceBlock name="customer-account-navigation-address-link" remove="true"/>   <!-- Orders link --> <referenceBlock name="customer-account-navigation-orders-link" remove="true"/>   <!-- Wish list link --> <referenceBlock name="customer-account-navigation-wish-list-link" remove="true"/>   <!-- Gift card link --> <referenceBlock name="customer-account-navigation-gift-card-link" remove="true"/>   <!-- Gift registry --> <referenceBlock name="customer-account-navigation-giftregistry-link" remove="true"/>   <!-- Reward points --> <referenceBlock name="customer-account-navigation-reward-link" remove="true"/>   <!-- Order by SKU --> <referenceBlock name="customer-account-navigation-checkout-sku-link" remove="true"/>

Hope this helps someone!

The post Managing My Account Navigation Links in Magento 2 appeared first on Inchoo.

Ground zero – planning phase

چ., 06/14/2017 - 18:46

If you have plans to start a new website on Magento and don’t know where to start, or if you already have an existing website and you’re thinking of revamping it, then you might find this article interesting.

Creating Magento websites might seem as a simple process that includes installing and configuring Magento, choosing some of the predefined themes available, importing products and setting payment and shipping options.

However, there is more that meets the eye. The truth is, there will always be some additional things you’d like to improve on the purchased theme and custom functionalities you’d like to add on top of the default Magento, so something that might seem simple and straightforward at start can become more demanding and require a certain amount of planning.

Also, in many cases you won’t even be interested in a purchased theme and you would like your site to be unique and tailored to your customers needs. You also might want to add additional layer and connect your Magento with 3rd party extensions and some outside systems (such as order management, shipping and accounting system, or ERP).

So what would be the best first step to do in a situations like this?

Projects with high level of complexity and large scale projects require a throughout planning and making crucial decisions right at the project start. Here at Inchoo we approach to these type of projects starting with initial discovery and planning phase which is a standalone process that precedes development.

Why is this phase important?

We believe that quality planning process is imperative for making a stable foundation to build upon, rather than making changes in the middle of development process, which is costly and time consuming.

During the planning phase we put focus on the following:

  • getting to know Client’s business and Client’s current workflows better,
  • researching Client’s competitors and their solutions,
  • identifying the key architectural elements of the site,
  • preparing plan for overall database design (products, attributes, attribute sets),
  • helping Client with deciding which Magento edition to choose (Community or Enterprise),
  • analysing Client’s current solution (if they already have an existing website) including design, traffic data and customer’s behaviour which helps us to make data driven decision for achieving best results.

During this phase, in coordination with the Client, we also plan out the best way to integrate Magento with custom functionalities, 3rd party extensions and an outside systems, making sure that all of them work seamless together.

Result of this process is a detailed technical documentation file which outlines the desired workflows in detail, technologies selected and the process of how to achieve the integration(s) as well as the respective timelines and proposal for performing all the work.

Who is usually involved in this process?

We successfully engage clients in the planning phase as we require valuable input from persons who work closely with the business (sometimes this is a Project manager, eCommerce manager or even a business owner).

On our side, for overall business case and workflows analysis, feature planning and SEO considerations we have a team of eCommerce consultants (Inchoo Consulting Group) and they make sure we deliver the best possible e-commerce solutions to our clients and ensure long-term success for Clients.

We also involve certified senior Magento backend and frontend developers for architectural planning and as well as UI designer for high-level usability discussions. They are all experts with years of experience in the eCommerce industry.

With that being said, deliverable of this process and our consulting work is a direct result of the knowledge, experience and time.

To conclude

Different development companies have different approaches and sometimes planning phase is not perceived as that important. Behind Inchoo success stories lies a well planned process which allows us to deliver high quality solutions for all our Clients.

If you find this article and our approach appealing to your needs and your project, contact us for more details.

The post Ground zero – planning phase appeared first on Inchoo.

Inchoo won The Golden Marten Award

چ., 06/14/2017 - 13:26

After 9 years in business, Inchoo won The Golden Marten Award (Zlatna kuna), traditionally given to the most successful local companies by the Croatian Chamber of Economy. We received it as the best small company in Osijek-Baranja County. Why did we win it for 2016? There were 21 distinct areas that were rated and Inchoo had very high scores in employment increase, average salary, non-material assets, financial stability and self-funding.

Osijek-Baranja County

President of County department of Croatian Chamber of Economy, Zoran Kovačević, has noted that all awarded companies have very high export ratio in total income. Inchoo has 85% of exports. Total income of our County is growing last three years. And only in 2016, it grew by 11%.

Other results are also quite good. International exchange is growing. Last year it went over 5 billion Croatian Kuna (HRK). Investments in long term assest are booming with the rate of 40%, primarly in food and paper industry, agriculture and water supply.


Last year, 2016, was very important for the company. Major event was a move to a new office space because it really introduced a new level of business. Besides the eternal focus on clients and projects, we worked a lot on internal organisation upgrades and new processes. This made our work more efficient and teams stronger. Comparing 2016 and 2015, number of employees grew by 25% and the income grew by 22%.

Pillar of our growth are the people. Not only our team, but the local community. Through the Osijek Software City association, we are organising many meetups, conferences, seminars and talks that have the same goal: to improve local ecosystem and make it more attractive. It is important for us that the young people in the community understand that they have a great perspective here in Osijek, which will motivate them to stay. Our region is battling with the strong emigration and we hope that the rise of software industry will invert negative trends.

The post Inchoo won The Golden Marten Award appeared first on Inchoo.

Bypassing Magento 2 layout update restrictions in Admin

س., 06/06/2017 - 15:12

Magento’s layout system has been vastly improved in Magento 2 to be more accessible, more powerful and to be more streamlined. But, for some reason, only a very small subset of layout functions is made available for use in Magento 2 Admin (category layout XML updates, to be more precise). In this article, we’re going to show a very simple way of bypassing this pesky restriction.

Layout update restrictions in Magento 2 Admin

In the interest of keeping the example simple and straightforward, let’s say we want to remove the page title element from a specific category. In Magento 2 admin, in the category layout update XML field we add the following line.

<referenceBlock name="page.main.title" remove="true" />

And when we click save, we get the following error:

Please correct the XML data and try again. Element ‘referenceBlock’: This element is not expected. Expected is one of (referenceContainer, container, update, move ). Line: 1

It’s important to note that this XML would be valid if added using XML files in a theme. It seems that different standards apply for the layout update field in Magento 2 Admin and for the theme layout files.

So, only the following XML is allowed:

  • referenceContainer – we can reference existing containers
  • container – we can create new containers
  • update – we can include various layout handles
  • move – we can move existing blocks around

This info will help us bypass the restriction.

Bypassing the layout update restrictions

We can simply bypass this restriction by wrapping our referenceBlock code in referenceContainer code. But we need to find the container which contains our page title element. By doing a simple search in IDE, we find the following code snippet.

<referenceContainer name=""> <!-- ... --> <block class="Magento\Theme\Block\Html\Title" name="page.main.title" template="html/title.phtml"/> <container name="page.messages" htmlTag="div" htmlClass="page messages"> <block class="Magento\Framework\View\Element\Template" name="ajax.message.placeholder" template="Magento_Theme::html/messages.phtml"/> <block class="Magento\Framework\View\Element\Messages" name="messages" as="messages" template="Magento_Theme::messages.phtml"/> </container> <!-- ... --> </referenceContainer>

We use the container and reference it in our Layout Update XML in Admin and wrap it around our initial code.

<referenceContainer name=""> <referenceBlock name="page.main.title" remove="true" /> </referenceContainer>

When we save this configuration, we do not get any errors on the category page in Admin and the page title block is removed on that specific category.


We hope to see these restrictions either removed from Magento 2 Admin XML layout update fields or better documentation that will explain the behavior in more detail. Magento 2 Admin would most certainly benefit of having unrestricted layout update features. Until then, we can hopefully use this bypass safely and hope that it’s upgrade-proof.

The post Bypassing Magento 2 layout update restrictions in Admin appeared first on Inchoo.

How to set Error / Maintenance page in Fastly CDN

س., 06/06/2017 - 10:53

The Fastly CDN will sometimes return a 503 error due to various issues that can occur. The generic text associated with a 503 error is “Service Unavailable” and it can mean variety of things. This default error response can be confusing to the customers and have a basic look and feel.

This guide will show you how to set friendly or prettier 503 custom error page through Fastly module which will be served when:

  • When origin returns a response status greater than 500
  • When origin is down (i.e unhealthy, timeout, etc)

To set custom Error page, go to:

Magento admin > Stores > Configuration > Advanced > System > Full Page Cache > Fastly Configuration

Under the Fastly Configuration, click on the Error/Maintenance page:

The modal window will pop up. Paste your custom HTML code into the HTML textarea and press the Upload button to save changes.

Now when Fastly returns 503 error, instead of default error page which looks something like this:

You will serve your custom error page:

That’s it! Check our blog for more Fastly articles, or contact us if you are in need of it’s integration.

The post How to set Error / Maintenance page in Fastly CDN appeared first on Inchoo.

Pagination with rel=”next” and rel=”prev” in Magento 2

چ., 05/10/2017 - 12:01

Out of the box, Magento 2 offers fair amount of search engine optimization options but when it comes to category pages, we only have option to add canonical meta tags. In today’s blog post, we will try to spice that up a bit by implementing our own variation of canonical tag and by adding rel=”next” and rel=”prev” tags to help bots with paginated content.

There are several ways to implement said functionality but the first step will most likely involve creating new Magento 2 module. I decided to implement our logic using event observer approach, so the first thing we do is configure our module to watch certain events. We do this by creating events.xml file in our modules etc/frontend folder followed by creating our observer class.

<?xml version="1.0"?>   <config xmlns:xsi="" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd"> <event name="layout_generate_blocks_after"> <observer name="categorySeo" instance="Inchoo\CategorySeo\Observer\Category" /> </event> </config>

As you can see from the XML above, we are observing layout_generate_blocks_after event. Since this event is not exclusive to category pages, first thing we do in our observer execute method is check if we are indeed on category view page. This is trivial since we already have full action name included in event object data.

if ('catalog_category_view' != $observer->getEvent()->getFullActionName()) { return $this; }  Replacing default canonical tag

We do this because in default implementation, canonical tag always points to root category URL, regardless of the page or filter combination applied.

To remove default canonical tag we will need category model instance. You could use registry (current_category) to retrieve it. In this example I used layout object instead since it’s also a part of the event object data.

/** @var \Magento\Catalog\Block\Product\ListProduct $productListBlock */ $productListBlock = $observer->getEvent()->getLayout()->getBlock('category.products.list'); $category = $productListBlock->getLayer()->getCurrentCategory();   /** * Remove default canonical tag */ if ($this->categoryHelper->canUseCanonicalTag()) { $this->pageConfig->getAssetCollection()->remove($category->getUrl()); }

We can now add our own canonical tag. To do that we will use pager block instance (\Magento\Theme\Block\Html\Pager) to generate our canonical URL and page config (\Magento\Framework\View\Page\Config) to insert it.

/** @var \Magento\Catalog\Block\Product\ProductList\Toolbar $toolbarBlock */ $toolbarBlock = $productListBlock->getToolbarBlock(); /** @var \Magento\Theme\Block\Html\Pager $pagerBlock */ $pagerBlock = $toolbarBlock->getChildBlock('product_list_toolbar_pager'); $pagerBlock->setAvailableLimit($toolbarBlock->getAvailableLimit()) ->setCollection($productListBlock->getLayer()->getProductCollection());   /** * Add rel canonical with page var */ $this->pageConfig->addRemotePageAsset( $this->getPageUrl([ $pagerBlock->getPageVarName() => $pagerBlock->getCurrentPage() ]), 'canonical', ['attributes' => ['rel' => 'canonical']] );

You might notice we are using our own getPageUrl method. It’s a slightly customized version of the method which can be found in \Magento\Theme\Block\Html\Pager class.

/** * Retrieve page URL by defined parameters * * @param array $params * @return string */ protected function getPageUrl($params = []) { $urlParams = []; $urlParams['_current'] = false; $urlParams['_escape'] = true; $urlParams['_use_rewrite'] = true; $urlParams['_query'] = $params;   return $this->urlBuilder->getUrl('*/*/*', $urlParams); }  Adding rel=”prev” and rel=”next”

Final step involves adding rel=”prev” and rel=”next” to indicate paginated content. By doing this we are informing search engine bots to treat these pages as a logical sequence, thus consolidating their linking properties and usually sending searchers to the first page.

/** * Add rel prev and rel next */ if (1 < $pagerBlock->getCurrentPage()) { $this->pageConfig->addRemotePageAsset( $this->getPageUrl([ $pagerBlock->getPageVarName() => $pagerBlock->getCollection()->getCurPage(-1) ]), 'link_rel', ['attributes' => ['rel' => 'prev']] ); } if ($pagerBlock->getCurrentPage() < $pagerBlock->getLastPageNum()) { $this->pageConfig->addRemotePageAsset( $this->getPageUrl([ $pagerBlock->getPageVarName() => $pagerBlock->getCollection()->getCurPage(+1) ]), 'link_rel', ['attributes' => ['rel' => 'next']] ); } Final thoughts

And that’s it! You should now have a working code which adds canonical, rel=”prev” and rel=”next” meta tags. While this is not a complete SEO solution, I like to think it’s a nice improvement of default functionality. Obviously there is a lot of room for improvement, for example we are not even considering product_list_limit and product_list_ordervariables or layered navigation filters, but that’s a story for another time.

The post Pagination with rel=”next” and rel=”prev” in Magento 2 appeared first on Inchoo.

This is why our clients never get penalized by Google

جمعه, 05/05/2017 - 14:32

Often, during an SEO audit, we figure out that the store that came to us for the audit suffered a manual or an algorithmical penalty from Google which resulted in a significant loss of organic traffic.

During the years we got pretty experienced in removing such penalties and getting the website back on the right track for clients that listened to our advice.

But, did you know our own clients who have a consulting retainer with us never got penalized by Google?

Here’s why…

Our clients never get penalized by Google because…

…we obey the rules. And we proactively warn our clients when they’re breaking the rules and getting themselves in danger of penalty. We monitor their websites to make sure none of their competitors are doing any negative SEO either.

This resulted in one simple fact that all of our clients in almost a decade of our existence that had a consulting retainer with us are completely free of Google penalties.

What are those secret rules that you obey?

Those rules are not secret at all. As the matter of fact, Google has them written down for you. Here’s exactly what causes penalties written by Google for everyone to easily see and understand.

But if that’s all it takes not to get penalized then why do so many online stores with professional SEO agencies get penalized anyway?

Because they don’t really follow the rules. They take “shortcuts” to ranking. They bend the rules. They feel comfortable in a “gray” area and risk penalties which eventually catch up to them.

How many times have you had an offer from an SEO agency to do link building for you? And they claim to be white hat because their specific link building technique is white hat?

Let me tell you the truth – no link building technique is white hat. They’re all breaking Google’s rules.

Only white-hat link that passes PageRank is a link you didn’t know you’ll get before you got it. That means links can’t possibly be built in a white-hat way. They can only be earned naturally.

But without breaking the rules there can’t be improvements in organic traffic

That is totally not true. As the matter of fact, we have a lot of happy clients whose cases prove the opposite is true. Playing by the rules and investing in quality technical on-site SEO instead of concentrating on link building pays off big time in the long run.

Here’s an example of a year over year organic traffic growth for one of our largest clients. We’re talking millions in extra revenue here. This is all achieved without breaking a single rule in Google’s eyes which means these results are here to stay and they don’t risk client’s business with potential penalties. As you can see, new user growth is larger than total traffic growth which means that this organic traffic increase is not caused by increase in brand awareness and growth in other acquisition channels. It’s actually the best traffic you can get, the organic traffic that’s acquiring new customers.

This is not a coincidence. We have a habit of delivering such results. We’ve been working with this client for quite a long time. Here’s organic traffic improvement for the same client which was achieved in 3 years time:

White-hat all the way

Following rules and being the best you can be on-site pays off big time in the long run. If you believe your store could be our next success story, get in touch with us today!

The post This is why our clients never get penalized by Google appeared first on Inchoo.

Magento 2: How to display static block content in modal overlay

پ., 05/04/2017 - 14:31

Many times we need to show some sort of information in modal overlay when customer comes to the site.
We can use it for many kind of purposes like newsletter subscription form, coupon codes or just some
general information.
In this article I’ll show you how to create the most basic functionality around this.

The challenge

When customer comes to our site, we want to show load specific static block content
into the modal overlay and show it only once to every customer.


We should start by creating new module in Magento 2.

For that purpose start by creating app/code/Inchoo/ModalOverlay/registration.php
with following content:

<?php /** * @category Inchoo * @package Inchoo_ModalOverlay * @copyright Copyright (c) Inchoo ( */ \Magento\Framework\Component\ComponentRegistrar::register( \Magento\Framework\Component\ComponentRegistrar::MODULE, 'Inchoo_ModalOverlay', __DIR__ );

Continue by creating app/code/Inchoo/ModalOverlay/etc/module.xml.
Put the following inside:

<?xml version="1.0"?> <!-- @category Inchoo @package Inchoo_ModalOverlay @copyright Copyright (c) Inchoo ( --> <config xmlns:xsi="" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> <module name="Inchoo_ModalOverlay" setup_version="1.0.0"> </module> </config>

That will create a new module in Magento 2.
What we want to do now is to create block that will be shown in modal.
For that purpose, let’s continue by creating another file called
This one should have the following content:

<?php   namespace Inchoo\ModalOverlay\Block;   use Magento\Cms\Api\BlockRepositoryInterface; use Magento\Cms\Api\Data\BlockInterface; use Magento\Framework\Exception\LocalizedException; use Magento\Framework\View\Element\Template; use Magento\Framework\View\Element\Template\Context;   /** * Class ModalOverlay * * @category Inchoo * @package Inchoo_ModalOverlay * @copyright Copyright (c) Inchoo ( */ class ModalOverlay extends Template { /** * @var BlockRepositoryInterface */ private $blockRepository;   /** * ModalOverlay constructor. * * @param BlockRepositoryInterface $blockRepository * @param Context $context * @param array $data */ public function __construct( BlockRepositoryInterface $blockRepository, Context $context, array $data = [] ) { $this->blockRepository = $blockRepository;   parent::__construct($context, $data); }   /** * Retrieve modal overlay content * * @param $identifier * @return bool|string */ public function getContent($identifier) { try { /** @var BlockInterface $block */ $block = $this->blockRepository->getById($identifier); $content = $block->getContent(); } catch (LocalizedException $e) { $content = false; }   return $content; } }

Newly created block needs to have a template, so let’s create it and initialize our JavaScript app/code/Inchoo/ModalOverlay/view/frontend/templates/modal_overlay.phtml

<?php /** * @category Inchoo * @package Inchoo_ModalOverlay * @copyright Copyright (c) Inchoo ( */ ?> <?php /** @var Inchoo\ModalOverlay\Block\ModalOverlay $block */ ?> <?php if ($content = $block->getContent('this-should-be-renamed')) :?> <div id="modal-overlay" style="display:none;"> <?php /* @noEscape */ echo $content ?> </div> <script type="text/x-magento-init"> { "*": { "Magento_Ui/js/core/app": { "components": { "modal_overlay": { "component": "Inchoo_ModalOverlay/js/modal_overlay" } } } } } </script> <?php endif;?>

Let’s add previously created block into layout on every page.
For that purpose, create app/code/Inchoo/ModalOverlay/view/frontend/layout/default.xml and
put the following inside:

<?xml version="1.0"?> <!-- @category Inchoo @package Inchoo_ModalOverlay @copyright Copyright (c) Inchoo ( --> <page xmlns:xsi="" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"> <body> <referenceContainer name="content"> <block class="Inchoo\ModalOverlay\Block\ModalOverlay" template="Inchoo_ModalOverlay::modal_overlay.phtml" name="modalOverlay" as="modalOverlay"/> </referenceContainer> </body> </page>

And finally, let’s add app/code/Inchoo/ModalOverlay/view/frontend/web/js/modal_overlay.js
with the following content:

/** * @category Inchoo * @package Inchoo_ModalOverlay * @copyright Copyright (c) Inchoo ( */ define([ 'uiComponent', 'jquery', 'Magento_Ui/js/modal/modal', 'Magento_Customer/js/customer-data' ], function (Component, $, modal, storage) { 'use strict';   var cacheKey = 'modal-overlay';   var getData = function () { return storage.get(cacheKey)(); };   var saveData = function (data) { storage.set(cacheKey, data); };   if ($.isEmptyObject(getData())) { var modal_overlay = { 'modal_overlay': false }; saveData(modal_overlay); }   return Component.extend({   initialize: function () {   this._super(); var options = { type: 'popup', responsive: true, innerScroll: false, title: false, buttons: false };   var modal_overlay_element = $('#modal-overlay'); var popup = modal(options, modal_overlay_element);   modal_overlay_element.css("display", "block");   this.openModalOverlayModal();   },   openModalOverlayModal:function(){ var modalContainer = $("#modal-overlay");   if(this.getModalOverlay()) { return false; } this.setModalOverlay(true); modalContainer.modal('openModal'); },   setModalOverlay: function (data) { var obj = getData(); obj.modal_overlay = data; saveData(obj); },   getModalOverlay: function () { return getData().modal_overlay; }   }); }); Conclusion

That is it. All that’s left is to create a static block and activate the module.
This should give you a basic module that you can modify however fits you best.

If you want to see how we can help you with these types of custom work on your Magento store, get in touch!

The post Magento 2: How to display static block content in modal overlay appeared first on Inchoo.

3 things you should check before you continue with your PPC campaigns

س., 05/02/2017 - 15:53

So you have been running an eCommerce site for some time now but in order to increase sales, natural thing to do is to increase traffic towards your site. Regardless of your site’s SEO health and organic ranking, PPC traffic is also something you shouldn’t miss out, because hey, your competitors are also doing it and being within the first 3 organic results today (if you are lucky) isn’t the same like a few years ago.

Paying for incoming clicks is natural thing to do but before you continue (start) investing money in driving traffic to your site, pay attention to these three essential things that we noticed many site owners miss out.

1. Functionality & usability check

Yeah, you played a giant role in setting everything up on your store and making sure it works for your visitors (because you are the one who knows your business the best). But stop just for a second and think about when did you do your last serious functionality and usability check.

This is your site and you know its every pixel as well as the right steps to take in order to find and buy specific product. But this probably doesn’t apply to your visitors. They might experience some real world issues that you haven’t notice and addressed as something that should be fixed. Each and every unnecessary questions in users head while browsing through your shop might prevent them from from proceeding to checkout… and that isn’t something you want.

Seriously consider adding a few objective parties to the whole story: ask your friends to test your site or hire some ecommerce professionals to do it for you. Actually you should do both. Although your site worked great some time ago, the world around you, the competitor’s sites and your customers’ habits changed so make sure you identify the new trends and functionalities in the checkout funnel and try implementing those on your site.

If you are struggling with the budget and that is the main reason why you haven’t hired proper help yet, just think about how much money each click costs – if it drives visitor to non functional site with poor usability – then regardless of the click price, it costs too much.

2. Observe & analyze your competitors and reconsider your current offers

By offers, I mean product prices, shipping and returns conditions, special offers, etc. Today’s customers get very well informed before they make the final buying decision because they are just a few clicks away from figuring out the place with the best bargain. They just need to open a few tabs more and they are ready to make a final decision. Don’t let your site to be only one of the “opened tabs”.

If your current conditions aren’t attractive as those on your competitors sites, maybe your should pause specific campaigns or bid less aggressively until you start offering a better deal.

Does this means that if I don’t have the best conditions out-there, I shouldn’t advertise at all? No, of course not, but if this is the case then you shouldn’t be surprised if you see poor ROAS. In order for someone to conclude that you are not offering the best conditions and that they are not going to buy from you, one has to click on your ad first (in many cases) – and all those clicks eat your advertising budget.

Be aware of the things your competitors do and make sure you are not missing out the conversions due to slightly higher product price.

3. Perform an in-depth analysis of your current campaigns to make sure your ads are correct and trustworthy

We had a few clients that didn’t pay enough attention to their ads and messages they convey through them. This means that they haven’t updated their campaigns for a while which lead to following situations:

  • Misleading ads. They have been driving traffic towards their site with incorrect messages about their special offers. Having something like “Up to 40% on all T-Shirts…” isn’t helping if you currently don’t have that offer on your site. It actually does you harm – because you are getting people that are about to become disappointing with the fact that they were misleadand you are spending your money on those clicks. Few days later, when you start your remarketing campaign and advertise the correct discount info, people will probably ignore your new ads as they won’t trust your anymore. Check all your ads and make sure they are correct and honest.
  • Incorrect or broken destination URLs. You’ve finally managed to attract person’s attention and made him to click on your ad. Instead of providing a state of the art landing page and user flow, you bring a person to the wrong landing page or even 404 page. Speaking of leaving a great first impression, right? Check your destination links to make sure this paid click lead a person to the thing he wants to find so he can add an item to cart and head over to checkout.

Think about these three common mistakes that we outlined in this blog post and make sure you are not repeating them. If you don’t have enough time to check everything by yourself, seriously consider to allocate a part of the PPC budget and hire a professional who could help you with that. You are maybe just a few dozens of consultation and development hours away from having much more intuitive and better functioning site that will convert much better than it does right now. If you don’t know where to start, check out our top selling audit service.

The post 3 things you should check before you continue with your PPC campaigns appeared first on Inchoo.

External database connection in Magento

پ., 04/27/2017 - 19:28

Most of the time working with Magento, a single database connection is just enough. Magento has excellent system of adding new tables in database or extending existing ones. So, why would there be a need for an external database connection outside the Magento system? Well, one of the examples is data migration from another ecommerce system. In this article, a simple connection to external database is explained with CRUD (create, read, update, delete) examples.


This external database connection is similarly defined as the Magento default one – in an XML configuration. The difference is that foreign connection is defined inside particular module’s XML configuration. It defines read and write adapters, setup and database credentials information. Foreign tables are defined in the same way as magento tables. They are under inchoo_foreignconnection_resource node so the model resource can be invoked later in the code. For demonstration purpose, there’s a frontend node in XML configuration that defines front name of the controller (fconn).

<?xml version="1.0"?> <config> <modules> <Inchoo_ForeignConnection> <version>1.4.2</version> </Inchoo_ForeignConnection> </modules> <global> <models> <inchoo_foreignconnection> <class>Inchoo_ForeignConnection_Model</class> <resourceModel>inchoo_foreignconnection_resource</resourceModel> </inchoo_foreignconnection> <inchoo_foreignconnection_resource> <class>Inchoo_ForeignConnection_Model_Resource</class> <entities> <product> <table>product_description</table> </product> </entities> </inchoo_foreignconnection_resource> </models> <resources> <inchoo_foreignconnection_write> <connection> <use>inchoo_foreignconnection_database</use> </connection> </inchoo_foreignconnection_write> <inchoo_foreignconnection_read> <connection> <use>inchoo_foreignconnection_database</use> </connection> </inchoo_foreignconnection_read> <inchoo_foreignconnection_setup> <connection> <use>core_setup</use> </connection> </inchoo_foreignconnection_setup> <inchoo_foreignconnection_database> <connection> <host><![CDATA[localhost]]></host> <username><![CDATA[username]]></username> <password><![CDATA[password]]></password> <dbname><![CDATA[db_name]]></dbname> <initStatements><![CDATA[SET NAMES utf8]]></initStatements> <model><![CDATA[mysql4]]></model> <type><![CDATA[pdo_mysql]]></type> <pdo_type><![CDATA[]]></pdo_type> <active>1</active> </connection> </inchoo_foreignconnection_database> </resources> </global> <frontend> <routers> <inchoo_foreignconnection> <use>standard</use> <args> <module>Inchoo_ForeignConnection</module> <frontName>fconn</frontName> </args> </inchoo_foreignconnection> </routers> </frontend> </config> Model

Next thing is a model that will use defined foreign connection to get data or to save data in a foreign database. Here, the model is initialized with the product table from XML configuration, that in this case defines product_description table.

class Inchoo_ForeignConnection_Model_Product extends Mage_Core_Model_Abstract { protected $_eventPrefix = 'inchoo_foreignconnection_product'; protected $_eventObject = 'product';   protected function _construct() { $this->_init('inchoo_foreignconnection/product'); } }

Model resource class is also defined with the same xml configuration node in _init() function, but with the TABLE_PRIMARY_KEY parameter. In this class, several functions can be created that will work with external data.

First example is createDataInResource function, which inserts data in model’s table. It takes array of parameters that will be inserted.

Second example is a readDataFromResource function that fetches all data from model’s table. Read adapter must be defined first. It is a configuration node from xml that defines read connection. After read adapter definition, Magento database functions can be used (select(), from(), limit(), etc..). When query is constructed completely, it can be executed with read adapter. Data can be retrieved with fetchPairs() or fetchAll() function. fetchAll() is used to get all records returned from mysql.

updateDataInResource and deleteDataFromResource functions take additional $id parameter that defines which record will be updated or deleted.

class Inchoo_ForeignConnection_Model_Resource_Product extends Mage_Core_Model_Resource_Db_Abstract { const TABLE_PRIMARY_KEY = 'product_id';   protected function _construct() { $this->_init('inchoo_foreignconnection/product', self::TABLE_PRIMARY_KEY); }   public function createDataInResource($values = array()) { $writeAdapter = $this->_getWriteAdapter(); try { $writeAdapter->insert( $this->getMainTable(), $values ); } catch (Exception $e) { Mage::log('Unable to insert data to external resource. ' . $e->getMessage(), null, null, true); } }   public function readDataFromResource() { $data = array(); $readAdapter = $this->_getReadAdapter(); $select = $readAdapter->select() ->from($this->getMainTable(), '*') ->limit(20);   try { $data = $readAdapter->fetchAll($select); } catch (Exception $e) { Mage::log('Unable to fetch data from external resource. ' . $e->getMessage(), null, null, true); }   return $data; }   public function updateDataInResource($id, $values = array()) { $writeAdapter = $this->_getWriteAdapter(); try { $writeAdapter->update( $this->getMainTable(), $values, self::TABLE_PRIMARY_KEY . '=' . $id ); } catch (Exception $e) { Mage::log('Unable to update data in external resource. ' . $e->getMessage(), null, null, true); } }   public function deleteDataFromResource($id) { $writeAdapter = $this->_getWriteAdapter(); try { $writeAdapter->delete( $this->getMainTable(), self::TABLE_PRIMARY_KEY . '=' . $id ); } catch (Exception $e) { Mage::log('Unable to delete data from external resource. ' . $e->getMessage(), null, null, true); } } } class Inchoo_ForeignConnection_Model_Resource_Product_Collection extends Mage_Core_Model_Resource_Db_Collection_Abstract { public function _construct() { $this->_init('inchoo_foreignconnection/product'); } } Usage in controller

All these functions are demonstrated in IndexController class but since they are defined in model’s resource class, they can be called in any controller class.

class Inchoo_ForeignConnection_IndexController extends Mage_Core_Controller_Front_Action { public function indexAction() { // Create $foreignProductCreate = Mage::getModel('inchoo_foreignconnection/product')->getResource(); $foreignProductCreate->createDataInResource( array( 'product_name' => 'Product name', 'product_description' => 'Product description' ) );   // Read $foreignProductRead = Mage::getModel('inchoo_foreignconnection/product')->getResource(); $result = $foreignProductRead->readDataFromResource(); var_dump($result);   // Update $foreignProductUpdate = Mage::getModel('inchoo_foreignconnection/product')->getResource(); $foreignProductUpdate->updateDataInResource( 3394, array( 'product_name' => 'Product name updated', 'product_description' => 'Product description updated' ) );   // Delete $foreignProductDelete = Mage::getModel('inchoo_foreignconnection/product')->getResource(); $foreignProductDelete->deleteDataFromResource(3394); } }

In most scenarios, Magento will use different type of external connection to retrieve or send data, but sometimes an external database connection like this will be the best way to go. One of the examples would be when you want to import products from another system to Magento with their xsell or upsell products. In that case, read connection would be used to retrieve product data and write connection would be used to save xsell or upsell product ids in a temporary table so they can be assigned to Magento product when all products from external system are imported. 

The post External database connection in Magento appeared first on Inchoo.

Experiences of running Magento 1 on PHP 7

س., 04/18/2017 - 15:59

How time flies! It’s been almost a year and a half since we released Inchoo_PHP7 extension for Magento 1 (, and announced that in a blog post (

We were just scratching our own itch – wanting to use all the performance benefits PHP 7 brought to run Magento faster. But, as the cover image of that post inadvertently prophesied, we created a monster that escaped, and is continuing to terrorize the villagers to present day.

So, what happened in the meantime?
  • M1 is still going strong. M2 will take over eventually, but, in my humble personal opinion, that’s going be a very slow process.
  • On the other hand, PHP 7 is overtaking PHP 5 much quicker than previous versions used to replace their predecessors. ( This is logical, because it really brings huge performance improvements, and it really is quite compatible, considering the major version number change.
  • Magento core became PHP 5.6 compatible in 1.9.3.x. Inchoo_PHP7 became PHP 7.1 compatible.
    • But, believe it or not, my humble personal opinion is that it’s better to run Magento on PHP 7.0 than 7.1 (
      It’s really difficult to say, but I guess there are hundreds of M1 sites powered by Inchoo_PHP. Just Inchoo alone built from scratch or upgraded double figure of sites to PHP 7. Community seems to be going strong with it too, so I think I can say that it is quite tried and true by now.
  • With help from community, we found and fixed a lot of edge cases, and can say quite comfortably that we can make pretty much any M1 site work on PHP 7 without a problem.
    • And, in the last release, we even created a testing shell script, which can be very useful to find and fix potential problems.
    • Just keep in mind that this still is, and always will be, a developer-level extension. It can be “install and forget” if you are lucky, but, it would be good to have someone knowledgeable to set up, test everything and fix any issues. We had clients who came to us just for this, and we were always able to help them upgrade to PHP 7. And I don’t even want to say you need Inchoo to set it up. There are a number of developers and agencies in the Magento community that can help you out.
What’s ahead?
  • Looks like M1 core will continue it’s evolution. Going to Composer install, PHP 7, full page cache on CE, etc. – these are all things that clients are demanding and Magento experts are able to provide. Whether someone likes it or not, the whole ecosystem is large enough to be able to live and evolve on its own, directed by market pressures, and not someone’s will.
  • 3rd party extensions are the part of code we can’t fix with our extension. So, whether you are a 3rd party extension creator, a client, an integrator or anywhere else in community, please help spread the awareness that it’s good for everyone to be PHP 7 compatible.
  • PHP 7.2 will remove Mcrypt extension, and M1 core is quite dependant on it. There are a few workarounds we already tried out, but it’s not going to be pretty. For the time being, stick to PHP 7.0, and you won’t have problems.
  • Personally, I can’t wait for the moment when I’ll be able to use PHP 7 features when programming Magento, not just it’s performance. Stronger typing, for one, should bring less bugs and a more secure system. But that is still in far future from now, unfortunately.



M1 runs (much) faster on PHP 7. Quite easy to set up due to a 3rd party module Inchoo_PHP7. MIT license. Great community support.

If you are having issues with performance of your Magento store, feel free to contact us to check technical state of your shop!

See you around!

The post Experiences of running Magento 1 on PHP 7 appeared first on Inchoo.