Great User Experience in E-Commerce starts with understanding customers!

How can we make an online shop that stands out better than overflowing competitors? Indeed online experience is offering useful information such as a comparison among several products with reviews. Researching became a typical behaviour for customers before making a decision. And there are even more interactions than only selling products on online shops.

In this article, I will describe the key practices how to capture customers needs in E-commerce by understanding them.

Continue reading about Great User Experience in E-Commerce starts with understanding customers!

Tags: , ,

A fairly complex Drupal Commerce site: freitag.ch

Freitag logoOur latest site with Drupal Commerce 1.x went live in July 2016. It is Freitag. Since then we’ve been adding several new commerce related features. I feel it’s time to write a wrap-up. The site has several interesting solutions, this article will focus on commerce.

First a few words about the architecture. platform.sh hosts the site. The stack is Linux + nginx +  MySQL + PHP, the CMS is Drupal 7. Fastly caches http responses for anonymous users and also for authenticated users having no additional role (that is, logged-in customers). Authcache module takes care of lazy-loading the personalized parts (like the user menu and the shopping cart). Freitag has an ERP system to which we connect using the OCI8 PHP library. We write Behat and simpletest tests for QA.

We use the highly flexible Drupal Commerce suite. 23 of the enabled Freitag contrib modules have a name starting with ‘commerce’. We applied around 45 patches on them. Most of the patches are authored by us and 15 of them have already been committed. Even with this commitment to solve everything we could in an open-source way we wrote 30.000+ lines of commerce-related custom code. Still, in March 2016 Freitag was the 3rd largest Drupal customer contributor.

Continue reading about A fairly complex Drupal Commerce site: freitag.ch

Tags:

Drupal SearchAPI and result grouping

In this blog post I will present how, in a recent e-Commerce project built on top of Drupal7 (the former version of the Drupal CMS), we make Drupal7, SearchAPI and Commerce play together to efficiently retrieve grouped results from Solr in SearchAPI, with no indexed data duplication.

We used the SearchAPI and the FacetAPI modules to build a search index for products, so far so good: available products and product-variations can be searched and filtered also by using a set of pre-defined facets. In a subsequent request, a new need arose from our project owner: provide a list of products where the results should include, in addition to the product details, a picture of one of the available product variations, while keep the ability to apply facets on products for the listing. Furthermore, the product variation picture displayed in the list must also match the filter applied by the user: this with the aim of not confusing users, and to provide a better user experience.

Continue reading about Drupal SearchAPI and result grouping

Tags: , ,

Order fulfillment with Swiss Post and YellowCube

Setting the stage

We live in a time where more and more goods are purchased online. May it be your airline ticket or the diapers for your newborn, many things are often cheaper and more conveniently purchased online. As comfortable it is for the customer buying things this way, as challenging it can be for the seller. They need to have an online presence that is easy to use and need to have all goods in stock to sell and send them quickly.

This means that selling physical products requires sufficient storage space on-site, people that handle picking, packing and shipping and someone that handles returned goods. All this factors can sum up to a costly venture, especially when you don’t have any infrastructure from other sales channels already.

Architekture PostLogistics YellowCube Connector

The PHP-YellowCube interface is part of all YellowCube extensions for PHP based web stores

What is order fulfillment?

This is where YellowCube comes in handy. YellowCube is a fulfillment service offered and run by Swiss Post. But what is a fulfillment service anyway? In the case of YellowCube it means everything to do with the storing and shipping of the products you sell on your store. This means receiving and storing of the products, handling of the inventory, picking, packing, shipping and handling of returns.

How to implement it into your web shop?

So far so good, but how does this translate into real life? Liip has, in close collaboration with Swiss Post, developed a PHP-YellowCube-SDK and also the integration for Magento and Drupal web shops. The PHP-YellowCube interface provides an object-oriented wrapper to the SOAP based interface provided by Swiss Post. The code is readily available on Github. Please feel free to contribute to the PHP-YellowCube-SDK, as well as the Magento extension or the Drupal extension.

Please explain…

Now that we know about the SDK, we need to know how the basic process works. I want to show you what needs to happen in order to implement YellowCube successfully into a web shop. The process is agnostic to a certain integration, so I won’t go into details how it is integrated in a specific shop extension. I will explain the basic process, which applies to all web shop integrations in the same manner (more or less).

Continue reading about Order fulfillment with Swiss Post and YellowCube

Tags: , , , ,

State of Drupal Commerce for Drupal 8

The two biggest players in the Drupal 7 webshop field are Drupal Commerce (also known as DC1) and Übercart. DC1 actually started as an Übercart rewrite to make use of Drupal 7 APIs. After the split Übercart was ported to Drupal 7 too but it was still using Drupal 6 technologies.

Although still very much in development, it seems something similar will be true for Drupal 8 as well. The developers of DC2 (the Drupal 8 version of Drupal Commerce), lead by Bojan Živanović rewrote the whole system from scratch to make use of the huge changes in Drupal 8. They are active members of the Drupal developer community so they not only know but also form the actual best practices. While working on DC2 they have fixed many dozens of Drupal 8 core issues and much more in other contributed modules (such as Entity, Inline Entity Form, Profile).

Continue reading about State of Drupal Commerce for Drupal 8

Tags:

Magento 2.0 Release

Finally Magento 2 has been released! I am especially glad as an ex-Magento employee. The Magento team has created a powerful and modern framework for eCommerce and I congratulate all of my ex-coworkers for this great milestone. But my post is not about that. Just after the release, there appeared a lot of blog posts that Magento 2 platform has changed the eCommerce world. But did it? In this post I am not going to describe all of the M2 bright sides (it has too many of them). My intend is to perform honest and objective M2 unboxing and to look inside of it from the point of view of the Magento community even if it’s going to be painful.

Magento Flag

Note: Magento 2 positions itself as an eCommerce solution and a ready-to-use product, not just a framework. Therefore my opinion about Magento 2 is based on this statement.

Continue reading about Magento 2.0 Release

Tags: ,

Auch die Letzten sollen endlich online gehen!

Alle Welt schreit Omni-channeling – dabei sind noch gar nicht alle Unternehmen richtig im E-Commerce angekommen.

(english version below)

Aber fangen wir mal von vorne an. Nach mehreren Jahren im Retail- und E-Commerce-Bereich hat es mich jetzt auf die andere Seite verschlagen und damit zu Liip. Wenn man bedenkt, dass ich die letzten Jahre im Onlinehandel Zuhause war – für jeden Aussenstehenden scheinbar eine logische Konsequenz in eine Webagentur zu wechseln. Auch mir erschien dieser Schritt durchaus logisch und als sich dann herausstellte, dass ich sogar E-Commerce-Projekte leiten darf, war mein Glück perfekt.

Meine Welt wurde komplett auf den Kopf gestellt, als ich angefangen habe, mir mein näheres retail- und e-commerce-lastiges Umfeld mal genauer anzuschauen. Dabei fiel mir auf, dass keines der Retail-Unternehmen, in denen ich früher gearbeitet habe, im Jahre 2015 einen Webshop besitzt. Klar ist ein Onlineshop für viele kleine wie auch grosse Detailhändler eine Herausforderung, der sich nicht jeder Retailer stellen möchte. In meinen Augen ist zumindest eine Website heute für jeden noch so kleinen Retailer ein absolutes Muss! Ein Onlineshop ist zwar nicht zwingend – das Fehlen eines Onlineshops aber auf jeden Fall eine verpasste Chance!

 Der Schritt vom erfolgreichen Retailer zum erfolgreichen E-Commerce-Unternehmen, am Besten sogar mit sehr gut ausgebautem Omnichanneling, ist ein beschwerlicher Weg. Das weiss auch die Geschäftsleitung, denn nicht wenige Unternehmen haben beim Versuch erfolgreiche Onlinehändler zu sein, eine schwindelerregend hohe Summe verbrannt und erholen sich nur langsam von dem Schock. Darüber hinaus stehen bei einem Entscheid für E-Commerce viele neue Prozesse, viele neue Mitarbeiter und viele neue Baustellen an, um die es sich zu kümmern gilt.

Dieser Schritt  ist mit der Eröffnung einer neuen Filiale zu vergleichen und benötigt viel Vorarbeit, viel Planung, viel Zeit,ein zuverlässiges Team und  verantwortungsbewusste Partner. Und wenn der (Online-) Shop erst eröffnet ist, muss man diesen weiter pflegen. Was im Kaufhaus der Filialleiter, Merchandiser oder Verkaufsmitarbeiter übernimmt, macht im Online-Shop der E-Commerce-Manager, der Web-Designer oder Online-Marketing-Manager. Und das was im Unternehmen der zuverlässige Lagerleiter ist, ist im Zeitalter von Ecommerce der Operationsmanager und der Entwickler. Anders gesagt: online und offline sind nicht so verschieden wie manch einer meint.

Ein anderes Beispiel: Welcher Retailer würde jemals einen fixfertig eingerichteten Shop kaufen? Übertragen auf den Online-Shop bedeutet dies, dass Liip nicht einfach den fertigen Online-Shop präsentiert. Verglichen mit einem Offline-Store arbeiten bei Liip Schaufensterdekorateur, Inneneinrichter, Logistiker und Personalplaner in einem Team nahtlos zusammen. Von Businesstrategie über Konzeption und Umsetzung bis zum langfristigen Betrieb aus einer Hand. So wird sichergestellt, dass während der “Bauzeit” des Shops nötige Anpassungen und bauliche Änderungen vorgenommen werden können.

Im Retail war ich es immer gewohnt, die Produkte so gut wie möglich in Szene zu setzen. Visual-Merchandiser verbringen Tage und Wochen damit, verblüffende Schaufenster zu gestalten. Aber warum starten so viele E-Commerce Projekte mit dem Design? Ich hätte niemals ein Schaufenster gestaltet, bevor der Shop geplant, gebaut oder gar eingerichtet worden ist.

Wenn die Grundlage das Fundament oder im Webbereich das Backend ist, der Innenausbau einem gut aufgesetzten CMS entspricht und ein zuverlässiges und motiviertes  Team in den Startlöchern steht, muss der Online Shop “nur” noch die gleichen Hürden überwinden, wie eine Offline Location.

E-Commerce: A rocky road we help you to smooth out

The whole world is talking about omni-channel even though, most companies don’t have an e-commerce solution yet.

But lets start from the beginning. After several years managing several retail businesses, I’ve changed sides, went behind the scenes and started a career as IT project manager for Liip.

My whole world stood upside down as I reviewed the business models of my former employers. None of them have a B2C e-commerce solution, even today! Sure, running an online shop is a challenge not every retailer wants to face, but in my opinion, an e-commerce solution is an absolute must!

But leaving the well-known tracks in retail towards a omni-channel strategy is a rocky road. There are more than a few examples of companies that burnt a staggering amount of money, just to get an e-commerce solution that won’t just quite fit to their business. For those companies, this is a blow they barely recover from, since e-commerce doesn’t just affect the web presence, it affects the whole company and it’s processes.

As a retailer, running an e-commerce business can be compared with the opening of a flagship store in the real world: A lot of planning, time and money has to be assigned to an enterprise of this scale. Considering the challenges, gearing up a successful e-commerce business is not that different from it’s real world counterpart. As long as you don’t have the right location, a proper workforce, a fitting interior and solid supply chain there is no use talking about what products you will display in your shopping window. This principle can also be applied to any e-commerce business. Why talk about the design first before you even got your processes in place? This is why we at Liip are determined to give you the whole picture of what it takes to get your e-business running. We do not just provide you with a design, we also shine a light on your processes and get you set up with all the points you have to tick before you can venture into a successful future with e-commerce.

Tags: , ,

Checking out Sylius: Symfony2 e-commerce

Last Friday we did a one day hackday with the goal of checking out the Symfony2 based e-commerce solution Sylius. Among the attendees were even two guests with Fabian and Stefano joining the Liipers David, Matteo, Patrick, Tobias and myself.

Getting started

We did not have any specific agenda and decided to just install and start exploring. For the most part this was a quite painless experience it just takes a while when 7 people clog up a wifi connection. Pawel had just completed the update for Symfony 2.3 the day before, so we found some minor bugs that we fixed. Stefano also submitted a PR to fix PDF generation on travis. Matteo spend some time updating the german translations.

Behat tests

Fabian decided to dig into the Behat tests which were failing on travis-ci.org due to memory issues. Sylius comes with a very extensive set of Behat tests. As a matter of fact maybe this is the best source of documentation of Sylius features. In the end his solution was to simply split the test execution by tag.

Adding some PHPCR love

One thing we noticed quickly while reviewing the database schema is the table used to store the ProductProperty class instances. It uses the Entity-Attribute-Value pattern, one of the reasons why its not so trivial to scale Magento. Essentially this is one commonly used approach to deal with unstructured data in an RDBMS while retaining some ability to run search queries. The big issues with the approach is that reading data out is quite hard but worse it basically requires one column for any kind of data being stored. In the case of Sylius its using a VARCHAR(255). So we figured we would simply use Doctrine listeners to modify the persisting to use PHPCR instead. The advantage being that with PHPCR it would allow to support all sorts of data types without length limitations. So this would for example allow to associated additional images, dates and longer descriptions with products. Stefano and I struggled a bit with the ORM listeners. We learned that persisted entities are not stored in the identity map until the RDBMS has actually generated an ID. Until then one has to use getScheduledEntityInsertions() to get access to the relevant entities. Once we figured that out the actual tasks of integrating PHPCR was comparatively trivial. Now it might however make sense to even go a step further and store the Product class itself in PHPCR as well using PHPCR ODM.

Dynamic routing

Sylius uses two “catchall” routes for products and categories. This is a quite common pattern found in CMS’s build on top of Symfony2 or many other general purpose web development frameworks. Basically one defines a route that simply catches anything below a specific pattern without knowing if anything even exists in the database that would match that. Then inside the controller a DB lookup is made and in case the data is missing a 404 is returned. In the Symfony2 CMF initiative we solved this need by introducing a chain router and dynamic router which has been adopted by ezPublish 5 and Drupal 8. It allows one to chain the standard Symfony2 router and any number of dynamic routers which means that static routes (like f.e. the homepage) do not need to be moved to the DB. The job of the dynamic router is to do a DB lookup during the routing stage. This means the controller is no longer responsible for this task. Stefano and I managed to implement this surprisingly quickly. One draw back of this approach is that now a DB lookup is also required to generate a route. Enabling the ORM entity cache however solved this problem quite easily.

Taxonomies for the CMF

So while Stefano and I worked in integration code form the CMF into Sylius, David attempted to do the opposite. He tried to integrate the SyliusTaxonomiesBundle into the CMF. However unfortunately he didn’t yet manage to get it to work.

Admintool

Matteo and Tobias looked a bit more deeply at the admin tool and unfortunately found several missing features. More over they quickly realized that the different tools allowed bringing the data to an inconsistent state. They then spend some time making the order status actually dynamic, at the time its was all hardcoded. They were still a bit unsure about the actual concept of how the order status relates to the relevant potentially several different shipping status states.

Sylius in the real world

Patrick is actually already running a Sylius web shop in a private project. So he spend some time investigating how to upgrade and what has changed. He found that indeed a lot of has changed but everything that has changed, changed for the better. However there are still things missing. For example in his project they needed additional notifications when an order is created.

Take away

Sylius looks really promising and we were positively surprised with the provided feature set. The code is clear and well structured and very easy to get started for a Symfony2 developer. However there are still important missing features making it very hard to plan the amount of time needed to do an actual real world project. The added fact that a lot of code is still very much in flux makes things even harder. It seems however that one could take the code at any point in time and complete a project with fairly well working code. In this regard the situation is quite similar to the CMF which has also already been used by several companies to build production applications. No doubt once Sylius has a stable release it will be a very viable alternative to Magento for projects that need very heavy customizations. In this sense it will also be interesting to see how OroCRM and Akeneo will turn out as these could provide some advanced CRM and product management capabilities that should be easily integrable since both of these applications are written in Symfony2 as well.

Integrating Magento into Symfony2

So last week four developers sat together on a regular Hackday to see what’s needed to hook up Magento into Symfony. To make this short the outcome is a Magento bundle for Symfony2.

When we met in the morning we weren’t even sure what exactly to try out but soon agreed on implementing a Symfony authentication which uses the Magento customer database.

Autoloader and Login

Starting our hacking, the first problem appeared quickly with incompatible class loaders: Unfortunately, the Magento class loader isn’t designed for missing class files, so every time Symfony tries to check for existence of a class which doesn’t exist there will be a fatal error. As we knew this problem from other projects a patch was already at hand.

Everything went quite smoothly then as integrating Magento into another project is basically just including the file app/Mage.php and then calling Mage::app(). Done.

Implementing the authentication itself seemed easy too as there is this simple method call in Magento which we added to our bundle within minutes to try out the login:

 

Session issues

But that’s where things got ugly: The sessions didn’t sync between Magento and Symfony. Integrating Magento without synced sessions doesn’t really make any sense as the user will loose his cart as soon as he browses from Magento to Symfony.

After a few hours of debugging and digging into both session handlers of Magento and Symfony the problem was found inside the __destruct methods. So here’s what happens:

  1. Symfony stores everything you save in the session inside SymfonyComponentHttpFoundationSession.
  2. During destruction phase inside Magento Mage_Core_Model_Resource_Session::__destruct() calls session_write_close() and saves the session content to the database (depending on your Magento configuration).
  3. Next SymfonyComponentHttpFoundationSession::__destruct() writes its own session information with the key _symfony2 into the session storage – too late!

The solution was to add a kernel.response event listener and call SymfonyComponentHttpFoundationSession::save() so the Symfony session content gets into the session storage before Magento saves it to the database.

Promising results

After solving the ugly session problem the only thing left was implementing an security provider for Symfony which authenticates the user against the Magento customer database. The result is a proof-of-concept Symfony Bundle which already provides some useful features to Symfony:

  • Login for Magento customers.
  • Synchronized session to access the shopping cart.
  • Full access to Magento products inside Symfony.

Integrating Magento into Symfony has been proven certainly possible and we had fun learning more about the session handlers of both Magento and Symfony.

At the moment there’s no specific project at Liip planning to use this bundle, so contribution is welcome on GitHub: https://github.com/liip/LiipMagentoBundle

Tags: , ,