gatsby-shopify-starter icon indicating copy to clipboard operation
gatsby-shopify-starter copied to clipboard

Clear cart on success?

Open mister-cairns opened this issue 5 years ago • 24 comments

Would there be any way to clear the cart once a transaction is complete? I can redirect from the Shopify checkout back to my site, but how to clear the cart as the users' products will still be in in the cart.

mister-cairns avatar Sep 20 '19 05:09 mister-cairns

Good point! I haven't even thought about that yet. I'll take a look at it!

AlexanderProd avatar Sep 20 '19 11:09 AlexanderProd

Perhaps a success/thank you template to redirect back to from Shopify that has a clear cart function in it?

mister-cairns avatar Sep 20 '19 12:09 mister-cairns

The cart automatically clears if you reload the page after finishing the checkout process. The problem is the checkout happens in another tab (on the Shopify site). I'll investigate further.

AlexanderProd avatar Oct 02 '19 15:10 AlexanderProd

Hi, I'm using your project as help for my site. Thanks a lot for your hard work. I'm having the same issue so let me know if you found a solution for it.

Chompas avatar Oct 03 '19 14:10 Chompas

Would it be a solution to refresh the content of the cart via API every x seconds, while the user is on the cart page?

Or show a modal window with button (please do checkout on other tab) after you clicked on the checkout. If he comes back and click the modal away, you reload the page.

rubas avatar Oct 25 '19 09:10 rubas

While it's not the cleanest approach, checking periodically if the cart has already been bought would be an option I guess.

The modal version would definitely work, the only thing I'm concerned of is that's a kind of unusual behavior since I don't know any other e-commerce page doing it that way. Don't think its a UX problem though.

The last option I've though of would be to just clear the cart after the user has clicked the checkout button. I'd suspect the checkout to go successfully in most cases, just when this is not the case the user might wonder why the cart is empty and he'd have to put everything in again. Would be a nice and easy solution for most times. But I'm clearly playing the probability card here.

AlexanderProd avatar Oct 28 '19 20:10 AlexanderProd

Perhaps a success/thank you template to redirect back to from Shopify that has a clear cart function in it?

I think this is definitely the best approach, probably a good spot for post purchase call to actions as well (social share, referrals, upsells, etc).

chanmathew avatar Dec 31 '19 08:12 chanmathew

Perhaps a success/thank you template to redirect back to from Shopify that has a clear cart function in it?

I think this is definitely the best approach, probably a good spot for post purchase call to actions as well (social share, referrals, upsells, etc).

Agreed on this. Has anyone built a straightforward example so far?

nandorojo avatar Apr 03 '20 17:04 nandorojo

My solution is as follows:

In Shopify, go to Settings > Checkout, and in the Addition Scripts section, add your redirect URL (I set a timeout so it wasn't instantaneous).

 <script type="text/JavaScript">
      setTimeout("location.href = 'https://your-url.com/thank-you/';",6000);
 </script>

I then created the thank you page template with a clear cart function:

import React, { useContext, useEffect } from 'react'
import StoreContext from '../context/StoreContext'

const ThanksPage = () => {
  const context = useContext(StoreContext)
  const { clearCheckout,checkout } = context
  useEffect(() => {
    if(checkout.lineItems.length !== 0) {
      clearCheckout()
    }
  },[checkout])

  return (

)}

export default ThanksPage

Hope that makes sense.

mister-cairns avatar Apr 15 '20 23:04 mister-cairns

Thank you! This is a great solution, I didn’t know you could add scripts to the checkout but it perfectly fixes the problem.

AlexanderProd avatar Apr 16 '20 07:04 AlexanderProd

Has this solution been implemented into master?

hoektoe avatar May 30 '20 13:05 hoektoe

@hoektoe The solution suggested by @mister-cairns needs to be implemented individually therefore I haven't merged it into the master.

AlexanderProd avatar May 30 '20 13:05 AlexanderProd

clearCheckout()

@mister-cairns How does your clearCheckout() function look like? Do you just remove all line items using removeLineItems() from Shopify js buy?

AlexanderProd avatar Nov 29 '20 08:11 AlexanderProd

Yup, this is what I use in mine:

import { useContext, useEffect, useRef } from 'react'
import StoreContext from 'src/context/StoreContext'

/**
 * Clear the user's cart when they're redirected to this thank you page.
 */
export const useThankYouClearCart = () => {
  const {
    checkout: { lineItems },
    removeLineItem,
  } = useContext(StoreContext)

  const isRemoving = useRef(false)

  useEffect(() => {
    if (!isRemoving.current) {
      isRemoving.current = !!lineItems.length
      lineItems?.forEach(({ id }) => {
        removeLineItem(id as string)
      })
    }
  }, [lineItems, removeLineItem])
}

If there's a function to remove multiple line items at once, even better.

nandorojo avatar Nov 29 '20 15:11 nandorojo

@nandorojo I've added your solution to my 'thank you' page but when I load it, only one line item gets removed. For every time I reload the page one more line item gets removed. Have you tested your solution with multiple items in the cart?

AlexanderProd avatar Dec 02 '20 14:12 AlexanderProd

Yeah, maybe try logging the line items in the effect to make sure they're all showing up?

nandorojo avatar Dec 02 '20 14:12 nandorojo

@nandorojo Yeah they're all showing up. How do you run your useThankYouClearCart() hook on your 'thank you' page? Just inside a useEffect() when the page loads?

AlexanderProd avatar Dec 02 '20 14:12 AlexanderProd

I call it at the top of the component file. You shouldn't put it inside of another useEffect. Could you share the file?

nandorojo avatar Dec 02 '20 14:12 nandorojo

Sure, this is how my file looks like, I had to rewrite your code in plain JS since I don't use TS in my project.

import React, { useEffect, useContext, useRef } from 'react'

import Page from '~/templates/Page'
import StoreContext from '~/context/StoreContext'

const ThankYou = () => {
  const { client, checkout, removeLineItem } = useContext(StoreContext)

  const isRemoving = useRef(false)

  useEffect(() => {
    const script = document.createElement('script')
    script.src = '/confetti.js'
    script.async = true
    document.body.appendChild(script)

    return () => {
      document.body.removeChild(script)
    }
  }, [])

  useEffect(() => {
    if (!isRemoving.current) {
      isRemoving.current = !!checkout.lineItems.length
      if (checkout.lineItems !== null && checkout.lineItems !== undefined) {
        checkout.lineItems.forEach(({ id }) => {
          removeLineItem(client, checkout.id, id)
        })
      }
    }
  }, [checkout.lineItems, removeLineItem, checkout.id, client])

  return (
    <Page title="">
      <div style={{ textAlign: 'center' }}>
        <h1>Thank you!</h1>
        <span role="img" aria-label="Heart">
          ❤️
        </span>
      </div>
    </Page>
  )
}

export default ThankYou

My removeLineItem function looks like this:

removeLineItem: (client, checkoutID, lineItemID) => {
      return client.checkout
        .removeLineItems(checkoutID, [lineItemID])
        .then(res => {
          this.setState(state => ({
            ...state,
            checkout: res,
          }))
        })

AlexanderProd avatar Dec 02 '20 14:12 AlexanderProd

Hmm, not sure why this works for me then.

Maybe try creating a removeLineItems in the StoreContext which receives an array of IDs, and pass that list of IDs from the useEffect?

Also, I think it makes sense to have the useThankYouPage-style hook as a standalone function so that you can export it for easier usage, but that's just a stylistic choice.

The problem could be the dependency array in the useEffect hook, though. Mine are a bit different.

I also have my removeLineItem function wrapped in useCallback. I would make sure to memoize like that.

nandorojo avatar Dec 02 '20 16:12 nandorojo

Has this issue been solved yet?

krichey15 avatar Mar 17 '21 22:03 krichey15

To my knowledge it hasn’t been solved, I’ve tried the technique with adding a script in the Shopify checkout section but it doesn’t work.

AlexanderProd avatar Mar 18 '21 05:03 AlexanderProd

To my knowledge it hasn’t been solved, I’ve tried the technique with adding a script in the Shopify checkout section but it doesn’t work.

I actually got mine to work

added this to Shopify:

And this was my thank you page

import React from 'react'
import ThanksText from '../components/SiteText/ThanksText';

class Thanks extends React.Component {
 constructor(props) {
   super(props)
 }

 componentDidMount() {
   localStorage.clear();
 }

 render() {
   return (
     <>
       <ThanksText  />
     </>
   )
 }
}

export default Thanks;

krichey15 avatar Mar 18 '21 06:03 krichey15

I implement @krichey15 solution and it works really well. Have anyone implemented some kind of polling or other type of checking on original cart page for checkout complete? So when user clicks "Checkout" on cart page new page/tab is opened and everything is done there also redirect to thank you page. BUT original cart page still shows that there is items in cart. There should be some kind of polling about when checkout is completed and original cart page refreshes and redirects to frontpage or somewhere.

Update: I solved this by changing checkout url to open same window:

  const handleCheckout = () => {
    window.location.assign(checkout.webUrl)
  }

kertzi avatar May 21 '21 04:05 kertzi