Twondo, a new webshop project was launched at the beginning of 2014.
The concept of the store is a Brand related multishop. But it also has other
shops in it. Currently the shop exists out of 8 shops.
Its a multishop, multidomain, multicountry and multilangual (in progress)
The domains are country specific: .be .nl .fr .de etc..
Currently the languages available are french and dutch.
See the modules page for a more detailed description of the site's functions.
How did we setup the multishop?
We used the domain access module for this one. We combined this with
subfolders domain module to get a path suffix instead of a subdomain.
For the multidomain part we realized this by just creating domain aliases.
Domain access module gave us great control over wich content to be placed
For our product listings we use the search api combined with the facet api
We removed the original commerce kickstart search indexes (wich were based on
the commerce_product entity) and replaced them with our custom node index
In total there are 2 search indexes.
1. The node (product) index with all the facets and content access
restrictions for our normal listings.
2. The second one is almost the same as our first, but we removed the index
and some restrictions.
The search api search engine (we combined this with views) has been made to
search both of the indexes. When you are on a non domain website (for example
http://twondo.com) and enter a search, we wanted it to search all products
When you search from a shop (for example http://twondo.com/garmin) we wanted
it to search products for that shop only.
Localization, the hardest part about this website.
We used the i18n module for this one (https://www.drupal.org/project/i18n).
The site is configured with 5 languages, but currently only 2 (3 if english)
We configured the site to use field translation instead of node translation,
this gave us more freedom in theming and reduced the amount of configuration
We wanted it to be easy for our customers to visit the site and find what
Because we wanted to reduce the amount of configuration needed for our
multisite and language paths we created a simple module for this.
We took 2 conditions in this module, one is a session and one is the domain
When the user visits the website from france, it will be using the .fr
extension and will be served with the french language.
But the user can switch to dutch and see the website in dutch on the .fr
Our payment provider is paybox, it had a module available for Drupal but it
didn't work the way we wanted it to, so we wrote one from scratch.
We used paypal as a reference for this and made it work almost the same.
Again, based on the country the user is surfing from, the payment methods
will be selected.
France has CB, Netherlands has Ideal.
Also we implemented paypal into the site, we used the default module, and
added commerce fee's to this and we bill 2% when this is used.
We only implemented this because some users want it. It was not a
The last payment module is Wire transfer, here we also used the default
module available on the commerce extensions page.
Currently we use the Belgian Bpost service for this. There was a module
available for this, but again it didnt fit into the webshop the way we wanted
so we developed a new one.
The original module shows a popup to the user, this is nog 2014 anymore.
Our bpost module makes all this happen on the backend, except for one part
where the user must select on a map from bpost. But instaid of showing this
in a popup, we changed this to work in a lightbox. All data gets verified
before the user completes his order.
For the order handeling we created a function (combined with a custom rule)
that when the order is complete the bpost shipping label gets generated in
Once the user visits the labelpage the label will be printed and can be
attached to the box for shipping.
The shipping cost is created with rules:
Free shipping based on order total
Paid shipping based on order total
Pickup at store is also a possibility.
For the system to work as fast and easy as possible, we integrated our system
with an external crm package. All orders, products get synced in one way
(shop to crm). Order statuses get updated as the order is being processed in
the external system.
For this we created our own module for xml communications.
We created a few datafeeds for external systems like beslist.be en
vergelijk.be, each product has their checkbox for each service in each
The xml's get generated on a nightly base using drush. We used views data
export for this.
These xml's are multilingual.
Product management (see screenshots)
We created a new module for easy product management.
We combined datatables with inline edit and our dymo label software for a one
does it (almost) all table.
The data gets fetched live from the database, all edits and changes happen
inline and the user can see what he has done, and still needs to do.
Also (see rules section) the user can see how much profit he has on a product,
what the prices are for wholesale and what the buyin price is.
The ean, sku, delivery speed, stock are also available.
The user can also enable, or disable the product from this system.
This list can be filtered, sorted and searched without leaving or refreshing
The are a few quick links on each product for the following actions:
Go to the edit page
View the product
Print dymo price label (small or big)
Of course we used views, and alot. Not going to explain much here. The views
are complex and make sure everything gets displayed on the correct website to
the correct user.
Minimal, rules, combined with views and commerce message.
Our mailing is complex. We send out 3 mails per order:
1. Confirmation email that the order has been placed. But if the user
selected wire transfer it receives different content (partial) with payment
Also when the customer is business (has a vat number) it splits up taxes
instead of just showing the order total.
This is all multilingual.
2. Our shipping mail, from the moment the user prints the shipping label, the
customer gets an e-mail with the tracking number.
3. The package leaves, the customer gets informed the package is on the way.
The template exists out of one TPL file, in this template we load blocks,
menu's and social media buttons, all based on the users location and
When the users changes something on the site, the mail will be updated
Custom Pricing, Taxes, Checkout, or Shipping Rules:
We created alot of rules.
Here is an overview what we did with rules:
Combine up to 5 articles, show them on the product and have the options to
calculate the price automatically or by a price you choose yourself.
We created a rule for this. But it required a custom action (feel free to ask
I'll share). At the point of development the module product bundle did not
work (as we wanted it to).
We created a rule, that does the following:
Grab the main product price (first one in the bundle).
Calculate the sum of all other products (accessory).
Give a 10% discount on the accessory and add it up with the main product
price. Then change the grouped article price to the new one.
This is of course conditional, if the user did not check the automatic
calculation check mark it just set the price to the one that was entered.
5 roles, 5 different prices and show them excluding vat.
That was the idea, and that is what we created.
First of we started by creating a new condition (filter by article group and
brand), we did this with a custom module for speed purposes ( just query the
database instead of loading full entity's etc..)
Then we create a rule with 3 simple steps
React on: calculate product price
Condition: our custom condition with catalog id and brand id (yes it is
taxonomy) and the required role.
Action: divide on the sell price OR multiply the buyin price (this is based on
Then we altered our custom price field display formatter to show the price
excluding vat, if the role has access to it. (yes we had to create a new role
This is all done by rules, no extra module needed. But here we used the
custom condition we created for the wholesale part.
Each rule is like the following (some small changes here and there but it
stays the same):
React on: calculate product price
Condition: User is normal (not wholesale) and category and brand, or entity
type is equal to.
Action: depends on what type of discount, can be fixed, can be percentage.
Here we added an extra action (component) to set 2 data fields on the product:
Promo class and promo text.
The extra fields will show on the product image, to show the user there's a
The site exists out of 17 content types (node types)
The amount of product variations types: 36
The amount of custom fields: Alot!
The amount of rules: 130!
The amount of roles: 10
The amount of menus: 19
Total taxonomy lists: 93
Total taxonomy terms: To much.
Enabled modules: 263
What to know something else? Feel free to ask, if possible i'll awnser or
It was an interesting project to work on, it was my first drupal commerce
project and I hope many will follow.
During development I learned alot about custom development, debugging an
issue, communicating with the community.
It was hard to develop and configure all of the modules and functions without
losing control of what had to be done.
If you are up to a project of this size, make sure you examine all modules
upfront, check what you need to get done and lay down all possibility's next
to each other. Sometimes it might be easier to develop a simple module
instead of configuring 10 rules.
Keep performance in mind, don't install a module for each thing but look at
other solutions to your problem.
Company / Freelancer
I personally did all the development, designing and configuration by myself.
Follow me on twitter if you want to: http://twitter.com/haringsrob
Interested in a project like this? Contact me http://easy-webdesign.be/
Marketing Opt In: Support the community! If checked, Commerce Guys may use
this showcase site to promote Drupal Commerce