Commerce Shipping brings a lot to the table

This week we finally packaged the full release of Commerce Shipping 2.0, and I couldn't be happier. Thanks to the efforts of my co-maintainer, googletorp, and contributors helior, cvangysel, and andyg5000, we have a solid shipping framework for Drupal Commerce that offers more flexibility and granular control than any other shipping system I've seen, Drupal or not.


Commerce Shipping checkout panes on the default checkout form.

What's the big deal?

As I wrote in the release notes, this milestone really is a big deal for Drupal Commerce. Among the many benefits this module brings to the table are:

  • The ability to use any number of shipping methods to calculate shipping rates on a site, using Rules to control when a particular method should be enabled. You can use one carrier to quote domestic rates, another to quote international rates, and a flat rate to offer free shipping if certain conditions are met.
  • An architecture that subdivides shipping methods into their individual shipping services (e.g. Ground, 2nd Day Air, Next Day Air, etc.), giving you granular control through Rules over which services should be available to an order. You might use this to ensure perishable products only ship overnight or to only offer guaranteed delivery dates for items in stock.
  • A shipping rate caching system that allows carrier rated quotes to be fetched in a single API request and stored locally (with an optional timeout) for the duration of the checkout process.
  • A shipping rate calculation API that lets you perform additional calculations on top of the base shipping rate for each service through custom modules or Rules. This allows you to add taxes, handling fees, discounts, and more to your shipping rates. It also turns the Flat Rate module into the basis for more complex shipping calculation schemes - weight based, quantity based, etc.
  • A checkout pane that can automatically recalculate shipping rates as customers enter their billing and shipping information. This lets you display accurate shipping rates that depend on address data on a single page checkout form.

Additionally, in conjunction with last month's Commerce 1.4 release, Drupal Commerce supports copying addresses and other matching field data between your billing information and shipping information checkout panes. Many thanks to the contributors mentioned above for working out all the kinks between this feature and the recalculation of shipping services.

This architecture removes limitations found in other open source eCommerce systems, like Ubercart and Magento, that often take an "all or nothing" approach to showing shipping services from any given carrier on the checkout form. Even better, features that this module delivers for free would actually cost you extra to add to systems like Magento that nickel and dime you through plugin marketplaces just to make your checkout form more customer friendly. Tongue

Next steps for Commerce Shipping

With this release there are already modules to support Flat Rate shipping, carrier rated quotes from UPS, FedEx, USPS, and others, and in store pickup facilitated by Kiala. Additional contributed modules focus on extending the system with other features, like joachim's Shipping Weight Tariff module that offers a simplified table based interface for setting shipping costs by total order weight.

Next steps involve bringing these contributed modules and their dependencies (like the Physical Fields module and Commerce Physical Products) to a full release, an effort already underway thanks to andyg5000 and other contributors / maintainers.

This work has been a community effort, and it has paid off for everyone. Smile

Executing arbitrary JavaScript from a Forms API #ajax callback

Drupal 7's Forms API included several sweet improvements making it easier than ever to build dynamic forms (with or) without writing custom JavaScript. I'm sure there are better summaries than I have time to bake up right now, but a quick list of pertinent properties includes #attached, #states, and #ajax. This post focuses on the #ajax property and how you can use it to execute arbitrary JavaScript during a form refresh.


A form element that uses #ajax to allow address copying in checkout.

Briefly stated, what I'm calling the form refresh is what happens when Drupal finally asks the callback function pictured above what response to send to the client. This can be one of two things:

  1. A piece of the form that will be rendered to replace the contents of the wrapper element specified in the #ajax array
  2. An array of AJAX commands to execute in the browser

We do both in Drupal Commerce, sometimes simply refreshing part of the form that has been updated and other times sending back a nice fat batch of commands to update various parts of the page. We use commands arrays to great effect to make attribute widgets on the Add to Cart form dynamically update product fields that have been rendered into node pages. This is how product images change based on the color selected, for example.

To create these commands, you use functions like ajax_command_replace(), which simply swaps out the contents of an element on the page with something else as if you'd used the first type of response. The other commands are mostly similar manipulations of the DOM, with the full list of commands available here.

I personally think we need more modules brave enough to use ajax_command_alert() in their #ajax callbacks. Cool

One thing you won't find in that list is something like ajax_command_eval() to execute some arbitrary JavaScript back at the client. We've had just such a need a couple times now, once in Commerce Shipping where I wanted to trigger a shipping rate recalculation when an address copy button was clicked and another time on a client site where updating attribute widgets on the Add to Cart form needed to trigger updates in a Flash based product customizer.

Our solution was to use ajax_command_invoke(), which executes a jQuery method with whatever arguments you pass it. Your module should first define a jQuery plugin to hold your code, which is surprisingly easy. Your form them needs to use the #attached property to ensure the JavaScript file is included when your #ajax enabled form element is rendered. Then you just have to invoke your custom jQuery method via ajax_command_invoke(), and you're golden.

This diff from the Commerce Shipping module shows this (hack?) in action. Theoretically, ajax_command_invoke() invokes a jQuery method on some element selected from the DOM, but this example currently just triggers another element's click event using a small jQuery plugin that breaks a design rule by returning nothing to chain to. C'est la vie.

Next Steps for Drupal Commerce

It was my pleasure to demo Commerce Kickstart 2.x at DrupalCon Munich as I presented Next Steps for Drupal Commerce. The relaunched distribution has been a long time coming, and I couldn't be happier with the release our Kickstart team at Commerce Guys has produced. They've proven the idea that we could keep the core of Drupal Commerce a slim eCommerce framework and wrap it in a usability layer that makes it both attractive and easier to administer.

Beyond the sheer amount of polish that has gone into the UI from the installer to the "Shiny" administration theme, its two most exciting features for me are the Inline Entity Form and Views Megarow functionality.


An inline entity form on a product display node with multiple variations.

Inline Entity Form allows us to embed product details forms inside node forms, simplifying the product vs. product display architecture that has made Drupal Commerce notorious (and truly flexible). I could write a whole post about just how we've implemented it, but I'll save the gory details for a later time.

I will at least point out that if this were a single value product reference field, instead of the drag-and-drop table pictured here, the module would simply embed the product related form elements directly into the node form.


A Views Megarow in action after clicking the "Quick Edit" link.

An equally impressive technical implementation, Views Megarow makes it simple to edit groups of products and orders inline in a View through some fancy AJAX row expansion. It gives you easy access to bulk product edit forms and order summaries complete with order activity streams and administrator comments.

Both of these features have been meticulously planned, designed, user tested, and revised to provide a very streamlined user experience for store administrators. With my time mostly focused on other development, I happily applaud our team for putting out such high quality work.

However, even with this release under our belts, we're hardly ready to sit back and relax. We have plenty more to do in the development of Drupal Commerce distributions, contributed modules, and the core framework itself. I spent the final part of my session at DrupalCon proposing the topics and timeline under consideration for a Drupal Commerce 2.x roadmap targeting Drupal 8.

To make sure we're meeting these challenges head on, I proposed a Commerce 2.x planning and development sprint at our offices in Paris in mid-October. The primary goal of the sprint is to research and plan development on Drupal 8, including how to best utilize and work with the various core initiatives, what new modules to add as dependencies or bring into core as new features, and what core code needs refactoring.

This sprint is on the calendar for October 15-19, and while we likely won't be laying down a lot of code, we're still looking for collaborators. We're particularly interested in folks with experience developing for Drupal Commerce on Drupal 7, bonus points awarded to those who have had to work around its limitations.

I'll post more on the topic in the near future, including specific items we intend to address in 2.x development. In the meantime, it's about time for a Commerce 1.4.

On Cats, Bags, and Letting it all out

One of the unexpected challenges in raising money to grow your business is keeping mum about the deal until it's time. Time is likely among the many terms you'll find defined in your contract, and between the day you sign the papers and the day that time actually arrives, you're glowing inside because your investors believe in the potential of your business and want to see you do more.

Investors don't magically make a business plan succeed, nor do they single out the sole source of success behind a business or an idea. This is certainly the case with Commerce Guys' raise announced last week. We know for a fact that our investors get open source as much as they do eCommerce. Even as they evaluated us on our ability to execute our business plan, they evaluated us on how well we work within and alongside the larger Drupal community. When they took a close look, they saw the strengths of the community and the caliber of developers collaborating with us to build Drupal Commerce.

That's what makes it so exciting to share the news - investors and developers who have grown their own businesses and, in the case of the team at Open Ocean with MySQL, their own open source projects have looked closely into both Commerce Guys and Drupal Commerce and felt confident enough to front some serious cash for us to kick our efforts up a notch. Many of these guys have built their own eCommerce systems and understand the challenges we're in a unique position to solve through Drupal 7, Views, Rules, and Commerce, and they're guys who understand the importance of the community in the success of any open source project.

So, we're not crazy after all, and what we've been trying to build with our friends at Commerce Guys and in the Drupal community isn't crazy. Ambitious, sure, but achievable. Our vision for Drupal Commerce remains the same - to see Drupal Commerce become the world's leading open source eCommerce framework. For the last two and a half years, my time has been set aside by Commerce Guys to develop the code (with plenty of help from other brilliant Commerce Guys and community contributors) and grow the community needed to make it happen. Now we've sold the vision to some very smart people with deep pockets outside our normal circles and are eager to see what happens next.

Their affirmation is much appreciated, but so is the money that will let us hire and set aside even more developers to "scale me" out a bit. We need to address immediate concerns pertaining to documentation and community support on DrupalCommerce.org. We'll need to make sure we follow-through on our longstanding 2.x strategy to bring some sanity to the user experience for administrators even as 1.x has privileged developers. All the while, there will be more than enough module maintenance and distribution work to go around!

Addressing these needs for Drupal Commerce should only require a fraction of the money we've raised, but it's a good start that will have an immediate positive impact on the thousands of people already using Drupal Commerce to power their online businesses. If you think you can stomach working with me on a daily basis and have the chops to help us succeed, be sure to get in touch.

Pages