Skip to content

Signup: Loop between checkout and plans #105027

@alshakero

Description

@alshakero

Context and steps to reproduce

  1. Go to /start.
  2. Pick a paid plan.
  3. You'll reach Checkout.
  4. Click on "Back" at the top and chose "Clear cart"
  5. You're back in Plans but clicking on "Back" at the top goes back to the checkout and then back to Plans forever.

Documenting for posterity

This issue is basically impossible to solve in a clean and 100% fail-proof way.

You have

Page 1 -> Page 2 -> Page 3

And your history stack looks like so

Page 3 <--- index
Page 2
Page 1

On Page 3 the user clicked a button that took them to Page 2. While the button is called "Back", it's really just a link to Page 2. So the browser will push Page 2 down the history stack, and the stack will look like this:

Page 2 <--- index
Page 3
Page 2
Page 1

When the user clicks the browser's Back button on Page 2, the browser moves the index down, and they will go to Page 3, but the user really means to go to page 1.

Page 2
Page 3 <--- index
Page 2
Page 1

Possible solutions

Solution I: Instead of calling window.location.assign call window.location.replace. That will break the loop indeed, but it will break the forward button from Page 2. Which is important because the Forward button goes to the checkout where the user pays.

Solution II: Instead of actually going to Page 2, we call history.back. This is nice because it keeps the stack intact and simply moves the index down. The Back buttons work on all pages, the forward buttons work on all pages, and all is good. Except there is no guarantee the user will go back to the desired page. They could have come from Google.com or their history could be empty. To mitigate those two risks, we can do the following:

  1. Check if the history stack length > 1. This means there is something to go back to.
  2. Check if the referrer is a WP.com property. This ensures we don't go back to Google.com.
  3. If these conditions are not met, we go to forceCheckoutBackUrl. This would normally break the history stack, but because conditions 1 and 2 are not met, we know the stack is already worthless.

Solution III: Keep a copy of the history stack in local or session storage and use it as a more robust source of the referrer. While this is more robust on paper, adding state to navigation is almost always a can of worms. It will assume both sides (checkout and onboarding) remain in agreement about the names and values of these storage keys and values.

I'll go with Solution II. It has the best tradeoffs.

Metadata

Metadata

Assignees

Labels

Needs triageTicket needs to be triaged[Type] BugWhen a feature is broken and / or not performing as intended

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions