I've been looking into making a single page checkout work for Commerce, and although there ways that work (see http://www.drupalcommerce.org/node/952) it doesn't work very well in more complex scenarios.

Single page checkouts are growing in popularity because it decreases CAR (Cart Abandonment Rate). Since Drupal Commerce is already very powerful e-commerce tool, making single page checkouts possible would in my opinion make it an even stronger competitor. It's also a feature that shop owners are requesting more and more.

It seems to me that Commerce currently needs page reloads at certain points in order to calculate the sell price. In the simplest scenario, that isn't really necessary, but when using Commerce Shipping, Commerce Coupon or other modules that alter the price, single page checkout becomes difficult to manage, since there's no built in ajax.

Now, I don't have the slightest clue what needs to be done in order to better support this, and perhaps it's something that solely depends on the contrib modules but I want to raise a discussion around it to get more input and discussion around it.

CommentFileSizeAuthor
#17 53d8f2d60077911c00a74e97.png190.61 KBvlad.dancer
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

AdamGerthel’s picture

Issue summary: View changes

added links

rszrama’s picture

Title: Single page checkout support » Provide better core support for AJAX reloading of checkout panes / pages
Version: 7.x-1.0-rc3 » 7.x-1.x-dev
Component: User experience » Checkout
Status: Active » Postponed

I think in general it's going to be the responsibility of modules that define those checkout panes to be updating the checkout form. This is possible using Drupal's core AJAX framework in the Forms API. It's what I intend to do with Shipping 2.x (see #1287124: Support recalculating shipping when the address is entered).

However, in core, we've had a longstanding idea that it would be helpful to provide better pane-by-pane form rebuilding to better support single page checkout. We can leave this postponed so we remember to come back to it for 2.x, but I'll retitle it since single page support is technically already there - just needs improvin'.

AdamGerthel’s picture

Alright so it basically comes down to contrib modules supporting it. But the shopping cart summary uses views. Wouldn't that view also need to refresh using ajax when shipping changes the price, or when a coupon is added?

rszrama’s picture

Nope, if we refreshed and replaced the whole form, it would be updated automatically. The main issue I see with this approach right now is that AJAX replacements in the Forms API cause some unsightly jitters of the whole page.

miaoulafrite’s picture

subscribing

while there is nice screencasts on taxes setup, it is very confusing for the "Shopping cart contents" view not to update, especially:
- taxes lines are not added / updated
- order total is not updated

considering shipping or coupon : it is contributed modules, fine
but taxes is built-in, and the view still does not update

i tried to use rules / taxes actions to fire some actions when a country / a state generates a new tax line to update the "Shopping cart contents" view without success

if this view doesn't update on the checkout page, it is meaningless, and therefore the "checkout page" would resume in a "user info / address" input only which also makes no sense

still talking about updating "Shopping cart contents" view when taxes changes, i would suggest to add the following feature:
- under "Store > Configuration > Taxes"
- when you click on "Configure component" and define how your tax is applied (ie: Order address component comparison : State = Colorado)
- you should be able to add an action "Refresh Shopping cart contents" view that you could put just below the built-in "Apply a tax rate to a line item"

then tax rate is applied, view gets refreshed and confusion is gone ;)
review order pane still reviews the order (when enabled)

i did not try coupon & shipment modules yet, but i guess - at least for shipping - the same principle based on address trigger would be enough

rszrama’s picture

The main issue here is that in many cases (if not a majority), you need to know the billing or shipping information of the order before you can effectively calculate taxes. A customer may be tax exempt or they may be shipping to a state where you don't have nexus. That's why we save display for the checkout form once we know the address.

That said, you could alter the cart block or form to use the Order Total area handler in the footer of the View that breaks down the total including taxes. As of 1.2 that's actually possible within the View.

miaoulafrite’s picture

thanks for your quick answer. still i don't understand something:

The main issue here is that in many cases (if not a majority), you need to know the billing or shipping information of the order before you can effectively calculate taxes. A customer may be tax exempt or they may be shipping to a state where you don't have nexus. That's why we save display for the checkout form once we know the address.

this is what i was pointing at: let say the billing / shipping is the first fieldgroup, then you have the "Shopping cart contents" view

once the address is known (first fieldgroup of checkout form), there is already some AHAH to display additional fields such as state if you select USA. I suppose this action also triggers the rule "calculate taxes". and therefore that would be possible to trigger another action "update view" (which is still just below). but it is probably wrong and the trigger is the "continue checkout" button unfortunately.

you could alter the cart block or form to use the Order Total area handler in the footer of the View that breaks down the total including taxes. As of 1.2 that's actually possible within the View.

could you please explain how? still i suppose it won't be updated on country / state change...

rszrama’s picture

Yeah, those are two separate processes. Re-rendering form elements from within that section of the form is fine for the Address Field module, but it has no clue where it will end up being displayed and whether or not anything else on the page will need to react to its updates. In other words, it's not trivial to refresh the rest of the page when something else on the page changes. This is compounded by the fact that re-rendering the cart contents section of the page would depend on the new address being saved to the order, which isn't technically supposed to happen until the form is submitted. We might fudge this, though; there's an open issue describing the proposal in the Commerce Shipping 2.x queue.

miaoulafrite’s picture

got it!

but still, if you don't use shipments, the problem is still there: selling to someone in another state / country would need to update the view anyway.

for a project on D6 i used views_flag_refresh which was reacting to a user even (flagging something) to update/refresh a view. Perhaps we could learn something from it? hum... well if the tax is not computed yet it is useless

ShaneOnABike’s picture

Status: Postponed » Active

Yeah in terms of Canadian taxes this is pretty important actually since the rules are pretty different depending on tax so it changes the actual total cost which a person doesn't realize until they have actually gotten to the payment page.

Is there any modules or work on this currently?

Zac_JH’s picture

Hi

Having spent far too much time trying to get a resilient working single page checkout I've now come to the conclusion that for Commerce 2 maybe this should be started from a fresh.

The need to use buttons to enable the ajax, incase some-one does not have JS is causing endless problems with creating a working and effective single page checkout. It's simply to complex having html forms, php/ajax & JS all working nicely together in all the various browsers. e.g. Having a shipping address update the shipping options, which in turn updates the basket and payment total, all with sequential html buttons that have to be clicked by JS and then waiting for the previous ajax to finish before starting the next one... Imagine if we add vouchers, loyalty schemes, stored addresses...

Instead, why not have a single page checkout module and the standard multiple page checkout. Both can be driven by the same panes info. Then if the single page module is running but the customer has js disabled they get routed to the multiple page checkout.

So a user with JS can go to the single page checkout where everything can be run through just ajax and remove a lot of the difficulties.

I would be interested to start work on this, but would like peoples thoughts on the approach and if it would cause problems anywhere else in Commerce?

Thanks

rockaholiciam’s picture

I am actually in need of this too and have been tinkering with the commerce modules to make them work together on a single page checkout interface. The idea of a separate module that does it sounds good and reasonable.

rockaholiciam’s picture

Issue summary: View changes

spelling error

donquixote’s picture

This is compounded by the fact that re-rendering the cart contents section of the page would depend on the new address being saved to the order, which isn't technically supposed to happen until the form is submitted. We might fudge this, though; there's an open issue describing the proposal in the Commerce Shipping 2.x queue.

This seems the key here.
I am trying to get this to work myself, and run into the same issue:
While the ajax update does fire (or you can make it fire), the shipping and billing profile are not created, and neither is the shipping line item.

I am already creating the shipping line item on ajax with a custom module, but the shipping and billing profiles are still missing. And I have the feeling I am on a shaky territory by creating this stuff manually.

donquixote’s picture

I think the direction should be to see the checkout as an ajax live-edit form of the order entity and attached entities like billing and shipping profile and shipping line item.

Every time you change any form field on a checkout pane, this should update the server-side order, including the creation of customer profiles and shipping line items if they don't exist.

Then every pane can get an ajax refresh based on the updated order entity.

Does this make sense?

donquixote’s picture

Hmm, I have to correct myself:
The reason the shipping cost was not calculated and the shipping profile not created was that other required information was missing: Name and phone number.

Of course it would be nice if the shipping cost could be calculated only from the address, disregarding fields that are not related to the address..

jessepinho’s picture

I think I agree with your comment in #13:

Every time you change any form field on a checkout pane, this should update the server-side order, including the creation of customer profiles and shipping line items if they don't exist.

But that may cause too much of a burden on the server, in which case it may make more sense to have some sort of "Continue" button on each pane to send an Ajax request with that pane's contents, and then display the following pane.

swim’s picture

Issue summary: View changes
vlad.dancer’s picture

FileSize
190.61 KB

It would be really awesome if we could do something like mentioned in #13. Something like checkout process . Maybe with drupal 8 we can create frontend using some js framework and use drupal as a service to send order data.

bojanz’s picture

Status: Active » Closed (outdated)

At this point in the Commerce 1.x release cycle it's too late for any official improvements.

Commerce 2.x continues to improve this problem area, most recently with #2710999: Implement ajax pane refreshing slated for the 2.12 release.
In my opinion, the real UX improvement would come from implementing #3016621: Implement an Single-Page / Accordion checkout flow plugin, because that approach increases interactivity while providing clear points at which the order should be persisted.