3
votes

I'm attempting to do the following: I'm building a standard HTML/PHP website. We'll have products on the site. When someone clicks "add to cart", the user will be directed to Shopify with their product info and that product will be added to cart (no problem so far...got this accomplished). When they click back in their browser to go back to the site (thus leaving the Shopify cart), I need to be able to show the product info on the site in the header. Something like "5 products | $168.00" ... basically allow the site visitor (who is not in shopify, but rather in the HTML site we built) to see the values in their cart and then checkout or view cart whenever they want.

I came across this: http://api.shopify.com/cart.html#show

I'm a bit of a newb at JSON and was looking for examples of what I'm trying to do, but not seeing them.

Anyone advice or someone pointing me in the right direction would be awesome.

4

4 Answers

8
votes

Shopify actually provides a JSONP formatted file assuming you're coming from the same domain (to access the Shopify cookies that identify the individual user).

In other words:

Let's say a Wordpress site lives at www.example.com

And the accompanying "Shop Site" would live at shop.example.com (make sure this domain is your primary domain on the Shopify side)

To access the cart from your Wordpress site and process it with jQuery into your template or page you could call:

jQuery.ajax({

    url: "//shop.example.com/cart.json",
    dataType: "jsonp",
    success: function( data ) {
        /* Template Code here */
    },
    error: function( jxhr, status, err ) {
        console.log("Error, status = " + status + ", err = " + err);
    }

});

The JSONP formatted file allows cross-domain AJAX calls to be made via some Javascript trickery.

2
votes

These two pages should help you:

Adding to the Cart from a remote website

I'm not sure what you're doing to add to the cart right now, but this is the 'right' way to do it. Seeing as you've already got this working I wouldn't worry too much.

To get the cart, you should use the AJAX API. This API allows you to pull the cart for the current user without using the REST version you linked to. That one is designed for doing much heavier lifting (e.g. get all current active carts). The AJAX version is much simpler and designed specifically for front-end use. In simple terms, just call

http://[the-shop].myshopify.com/cart.js

and you'll get back the cart contents for the current session in JSON. It'll look something like this:

{
"items": [
    {
        "handle": "aquarius",
        "line_price": 6000,
        "requires_shipping": true,
        "price": 2000,
        "title": "aquarius - medium",
        "url": "/products/aquarius",
        "quantity": 3,
        "id": 30104042,
        "grams": 181,
        "sku": "",
        "vendor": "the candi factory",
        "image": "http://static.shopify.com/s/files/1/0040/7092/products/aquarius_1.gif?1268045506",
        "variant_id": 30104042
    },
    {
        "handle": "amelia",
        "line_price": 4000,
        "requires_shipping": true,
        "price": 2000,
        "title": "amelia - medium",
        "url": "/products/amelia",
        "quantity": 2,
        "id": 30104012,
        "grams": 200,
        "sku": "",
        "vendor": "the candi factory",
        "image": "http://static.shopify.com/s/files/1/0040/7092/products/2766315_da1b.png?1268045506",
        "variant_id": 30104012
    }
],
"requires_shipping": true,
"total_price": 10000,
"attributes": null,
"item_count": 5,
"note": null,
"total_weight": 947

}

1
votes

In case anybody has the same problem. Kameron's answer solved my issue. Remember to change ".js" to ".json" if you are setting dataType as "jsonp"

0
votes

After trying numerous different approaches, including the previous answers, this is the only thing I found that worked. The strategy is to set a cookie containing the desired information (in this case the number of items in the cart) on the parent domain, so that it can be accessed by another web site that has the same parent domain.

It requires a custom domain on the Shopify store, i.e. will not work with xxxx.myshopify.com.

Add a new Javascript file (e.g. cart.js) into the Shopify code Assets:

function extractDomain(host) {
    let parts = host.split(".");
    parts.shift();
    return parts.join(".");
}

function updateCartCountCookie() {
    fetch('/cart.json')
        .then((data) => {
            data.json().then((cart) => {

                let myDate = new Date();
                myDate.setMonth(myDate.getMonth() + 1);

                document.cookie = 'kh_cart_item_count=' + cart.item_count.toString() + ';expires=' + myDate
                    + ';domain=.' + extractDomain(location.hostname) + ';path=/';
            });
        });
}
/*
 This event fires after cart changes. This is theme dependent and may need to be different.
*/
document.addEventListener("theme:loading:end", () => {
    updateCartCountCookie();
});
/* update on initial load */
document.addEventListener('DOMContentLoaded', () => {
    updateCartCountCookie();
}

Include this in your theme template:

    <script src="{{ 'cart.js' | asset_url }}" defer></script>

Now the cookie kh_cart_item_count will be set on the parent domain with the number of items in the cart.

In your external website hosted on a sibling domain add this html snippet wherever you want the cart to appear:

<script>
    function getCookieValue(a) {
        var b = document.cookie.match('(^|;)\\s*' + a + '\\s*=\\s*([^;]+)');
        return b ? b.pop() : '';
    }
    document.addEventListener("DOMContentLoaded", () => {
        let count = getCookieValue("kh_cart_item_count");
        let el = document.getElementById("kh-cart-count")
        if (el) {
            el.innerText = count.toString();
            if (!!count && parseInt(count) !== 0)
                el.classList.remove("invisible");
        }
    });
</script>
<style>
</style>
<a href="https://shop.example.com/cart" class="kh-cart-count ml-auto mr-1">

    <svg class="icon icon--cart" viewBox="0 0 27 24" role="presentation">
        <g transform="translate(0 1)" stroke-width="2" stroke="grey" fill="none" fill-rule="evenodd">
            <circle stroke-linecap="square" cx="11" cy="20" r="2"></circle>
            <circle stroke-linecap="square" cx="22" cy="20" r="2"></circle>
            <path d="M7.31 5h18.27l-1.44 10H9.78L6.22 0H0"></path>
        </g>
    </svg>
    <span id="kh-cart-count" class="kh-cart-count invisible">0</span>
</a>

And add this css in an appropriate css file:

/* shopping cart icon style */
.kh-cart-count {
  width: 4rem;
  height: 4rem;
  display: flex;
  justify-content: right;

  span {
    font-size: 0.8rem;
    font-weight: bold;
    background: #ff0000;
    color: #fff;
    padding: 1px 1px 1px;
    -webkit-border-radius: 20px;
    -moz-border-radius: 20px;
    border-radius: 20px;
    height: 1.2rem;
    width: 1.2rem;
    margin-left: 1.5rem;
    justify-content: center;
    align-items: center;
    position: absolute;
  }

  svg {
    width: 2rem;
    height: 2rem;
    position: absolute;
  }
}

This won't automatically update if the website is open in a window when the cart is updated in a different window, but will update on each page refresh (or you could poll it with e.g. window.setInterval(updateCartCount, 10000); - there is a draft spec for a cookie change event but it's not yet available.)

The result looks like this:

Cart with number

You could obviously extend this to pass other data besides just the cart item count.