Difference between revisions of "Using the Spiffy Ajax API"

From Spiffy Stores Knowledge Base

Line 315: Line 315:
 
"The product 'VARIATION' is already sold out"
 
"The product 'VARIATION' is already sold out"
 
</pre>
 
</pre>
 +
 +
If there are items in stock, then it is possible add these items to the cart. The actual number of items requested are ''reserved'', but the actual inventory check is not performed until the customer proceeds to the checkout where the actual number of items ordered may need to be reduced if there are not enough still in stock to meet the requested number.
  
 
=== <code>GET /cart.js</code> ===
 
=== <code>GET /cart.js</code> ===

Revision as of 12:47, 27 August 2015

You can access the Spiffy Ajax API from your theme to enhance your customers' experience on your store.

The Spiffy Ajax API allows your customer to add items to the cart, update quantities in the cart and fetch information about the cart, all without requiring a page refresh. You can use the API to create 'add to cart' buttons that keep the customer on the product pages.

The Spiffy Ajax API also allows you to directly fetch information about a particular product using its handle.

Simple Access using the Wrapper Library

If you are using the jQuery JavaScript framework in your theme, then you can use the Spiffy Ajax API wrapper library to simplify the use of the API.

Of course, it's not necessary to use the wrapper library, or to code in jQuery to use the Ajax API, but if you do use the wrapper library, then a lot of the detailed API access work has already been done for you.

To use the Spiffy Ajax API jQuery wrapper library, you will need to include the following code in your theme.liquid file.

{{ 'jquery.js' | global_asset_url | script_tag }}
{{ 'api.jquery.js' | global_asset_url | script_tag }}

Wrapper Library Function Reference

Spiffy Ajax API Reference

GET /products/<product-handle>.js

Retrieve a product using the product handle and return the results as a JSON representation of the product.

Example:

{
  "id": 3121506,
  "title": "T-Shirt",
  "handle": "t-shirt",
  "url": "/products/t-shirt",
  "description": "<p>Featuring distressed edges & short sleeves.</p>",
  "created_at": "2008-07-16T08:25:09+10:00",
  "updated_at": "2015-06-24T14:04:58+10:00",
  "vendor": "Spiffy Stores",
  "type": "T-Shirts",
  "tags": [
    "clothing",
    "t-shirt"
  ],
  "price": "16.30",
  "price_max": "19.45",
  "price_min": "16.30",
  "available": true,
  "price_varies": true,
  "compare_at_price": "0.00",
  "compare_at_price_max": "12.59",
  "compare_at_price_min": "0.00",
  "compare_at_price_varies": true,
  "images": [
    {
      "id": 1840,
      "product_id": 3121506,
      "type": "Product",
      "position": 1,
      "alt": "",
      "src": "http://mystore.spiffystores.com/sites/1/products/1506_limet_000_full.jpg"
    },
    {
      "id": 1841,
      "product_id": 3121506,
      "type": "Product",
      "position": 2,
      "alt": "",
      "src": "http://mystore.spiffystores.com/sites/1/products/1506_tealt_000_full.jpg"
    }
  ],
  "featured_image": {
    "id": 1840,
    "product_id": 3121506,
    "type": "Product",
    "position": 1,
    "alt": "",
    "src": "http://mystore.spiffystores.com/sites/1/products/1506_limet_000_full.jpg"
  },
  "options": [
    "Size",
    "Colour",
    "Thread Colour"
  ],
  "option_values": [
    [
      "S",
      "M",
      "L",
      "XL",
      "XXL",
      "XXXL"
    ],
    [
      "Orange",
      "Green",
      "Purple",
      "Red"
    ],
    [
      "Teal",
      "Yellow"
    ]
  ],
  "option_combos": [
    [
      "0.0",
      "Teal"
    ],
    [
      "0.6297373387",
      "Yellow"
    ]
  ],
  "variant_option_index": 2,
  "variants": [
    {
      "id": "1691_0",
      "title": "S/Orange Teal",
      "price": "16.30",
      "compare_at_price": "0.00",
      "discount": "0.00",
      "available": true,
      "inventory": true,
      "inventory_quantity": 10,
      "inventory_management": "spiffy",
      "inventory_policy": "deny",
      "weight": 100,
      "sku": "SHIRT002",
      "barcode": "",
      "requires_shipping": true,
      "taxable": true,
      "free_shipping": false,
      "ship_separately": false,
      "option1": "S",
      "option2": "Orange",
      "option3": null,
      "options_id": 0
    },
    {
      "id": "1691_1",
      "title": "S/Orange Yellow",
      "price": "16.69",
      "compare_at_price": "0.00",
      "discount": "0.00",
      "available": true,
      "inventory": true,
      "inventory_quantity": 10,
      "inventory_management": "spiffy",
      "inventory_policy": "deny",
      "weight": 100,
      "sku": "SHIRT002",
      "barcode": "",
      "requires_shipping": true,
      "taxable": true,
      "free_shipping": false,
      "ship_separately": false,
      "option1": "S",
      "option2": "Orange",
      "option3": null,
      "options_id": 1
    },
    {
      "id": "1690_0",
      "title": "M/Green Teal",
      "price": "16.61",
      "compare_at_price": "0.00",
      "discount": "0.00",
      "available": true,
      "inventory": true,
      "inventory_quantity": 93,
      "inventory_management": "spiffy",
      "inventory_policy": "deny",
      "weight": 100,
      "sku": "SHIRT001",
      "barcode": "",
      "requires_shipping": true,
      "taxable": true,
      "free_shipping": false,
      "ship_separately": false,
      "option1": "M",
      "option2": "Green",
      "option3": null,
      "options_id": 0
    },
    
...
    {
      "id": "2137_1",
      "title": "XXXL/Orange Yellow",
      "price": "19.84",
      "compare_at_price": "12.59",
      "discount": "0.00",
      "available": true,
      "inventory": true,
      "inventory_quantity": 20,
      "inventory_management": "spiffy",
      "inventory_policy": "deny",
      "weight": 0,
      "sku": "SHIRT007",
      "barcode": "",
      "requires_shipping": true,
      "taxable": true,
      "free_shipping": false,
      "ship_separately": false,
      "option1": "XXXL",
      "option2": "Orange",
      "option3": null,
      "options_id": 1
    }
  ],
  "exchange_rate": 0.6297373387,
  "currency": "GBP"
}

Example call using jQuery:

jQuery.getJSON('/products/t-shirt.js', function(product) {
  alert('The title of this product is ' + product.title);
});

POST /cart/add.js

A product variation can be added to the cart using this call.

POST data is required and takes the form:

{
  id: 234234,
  quantity: 2
}

If the product uses custom options, then a composite variation id is used indicate which combination of custom options is to be used with the variation.

{
  id: '334234_1',
  quantity: 2
}

The quantity indicates how many items you wish to add to the cart for the specified variation.

The data can also be sent from a form if it is serialized.

  jQuery.post('/cart/add.js', $('form[action="/cart/add"]').serialize());

Only a single variation can be added to the cart with this Ajax request. Multiple variations can be added by queuing up several Ajax requests synchronously.

If the variation is added to the cart successfully, the cart line item is returned in JSON format.

{
  "cart_index": 1,
  "variant_id": 1771,
  "product_id": 1504,
  "options_id": 1,
  "title": "Artichoke - Tiny - Silk metallic<span><br/>Signs<br/>Sign 10% Off</span>",
  "price": "6.77",
  "discount": "1.35",
  "quantity": 2,
  "line_price": "12.19",
  "sku": "9111003",
  "grams": 20,
  "note": null,
  "taxable": true,
  "message": "",
  "vendor": "Spiffy Stores",
  "url": "/products/artichoke",
  "image": "/site/products/1504_artichoke_01_full.jpg",
  "handle": "artichoke",
  "product_title": "Artichoke",
  "product_description": "The Globe Artichoke is a perennial thistle originating in southern Europe around the Mediterranean. It grows to 1.5-2 m tall, with arching, deeply ...",
  "product_type": "Vegetables",
  "variant_title": "Tiny",
  "variant_options": [
    "Tiny"
  ],
  "requires_shipping": true
}

If the item is already in the cart, then the quantity will be equal to the new quantity for that item.

If a non-existent variation is added to the cart, an error will be returned instead, as follows:

{
  "message": "Cart Error",
  "status": 422,
  "description": "Variation not found"
}

All error messages are returned as JSON data structures.

The error code is:

422 (Unprocessable Entity)

Other errors may be returned if exception conditions with the cart are detected. For example, each cart supports only a limited number of items and if this value is exceeded, then an error is returned.

If an item is sold out, then the error message returned is:

"The product 'VARIATION' is already sold out"

If there are items in stock, then it is possible add these items to the cart. The actual number of items requested are reserved, but the actual inventory check is not performed until the customer proceeds to the checkout where the actual number of items ordered may need to be reduced if there are not enough still in stock to meet the requested number.

GET /cart.js

Use this to get the cart as JSON.

Response The JSON of the cart.

Example:

{

 "token": "1d19a32178501c44ef2223d73c54d16d",
 "note": "hello!",
 "attributes": {
 },
 "total_price": 15800,
 "total_weight": 0,
 "item_count": 2,
 "items": [
   {
     "id": 794864229,
     "title": "Red Rain Coat - Small",
     "price": 12900,
     "line_price": 12900,
     "quantity": 1,
     "sku": null,
     "grams": 0,
     "vendor": "Spiffy Stores",
     "properties": null,
     "variant_id": 794864229,
     "gift_card": false,
     "url": "/products/red-rain-coat?variant=794864229",
     "image": "http://spiffyserver.com/s/files/1/0040/7092/products/red-rain-coat.jpeg?v=1402604893",
     "handle": "red-rain-coat",
     "requires_shipping": true,
     "product_title":"Red Rain Coat",
     "product_description":"A bright red rain coat for rainy days!",
     "product_type":"Coat",
     "variant_title":"Red",
     "variant_options":["Red"]
   },
   {
     "id": 794864101,
     "title": "Gray Fedora",
     "price": 2900,
     "line_price": 2900,
     "quantity": 1,
     "sku": null,
     "grams": 0,
     "vendor": "Spiffy Stores",
     "properties": null,
     "variant_id": 794864101,
     "gift_card": false,
     "url": "/products/gray-fedora?variant=794864101",
     "image": "http://spiffyserver.com/s/files/1/0040/7092/products/gray-fedora.jpeg?v=1402604885",
     "handle": "gray-fedora",
     "requires_shipping": true,
     "product_title":"Gray Fedora",
     "product_description":"A gray hat for looking cool!",
     "product_type":"Hats",
     "variant_title":"Gray",
     "variant_options":["Gray"]
   }
 ],
 "requires_shipping": true

}

Example of a response for an empty cart:

{

 "token": "1d19a32178501c44ef2223d73c54d16d",
 "note": null,
 "attributes": {},
 "total_price": 0,
 "total_weight": 0,
 "item_count": 0,
 "items": [],
 "requires_shipping": false

}

POST /cart/update.js

Use this to change cart attributes, the cart note, and quantities of line items in the cart.

POST data

{

 quantity: 1,
 id: 794864053

}

Where quantity is the new quantity you want for a particular item, and id is the variant ID of that line item. You can also send a serialized cart form.

Response The JSON of the cart. Reminder

This is what you will use to submit cart attributes and a cart note.

If the cart is empty the following jQuery snippet will add 2 of variant 794864053 and 3 of variant 794864233:

jQuery.post('/cart/update.js', {updates: {794864053: 2, 794864233: 3}});

This version will yield the same result:

jQuery.post('/cart/update.js', "updates[794864053]=2&updates[794864233]=3");

If you send the following you will update the quantity of 794864053 to 5:

jQuery.post('/cart/update.js', {updates: {794864053: 5}});

Finally, you can remove both 794864053 and 794864233 from the cart with the following:

jQuery.post('/cart/update.js', {updates: {794864053: 0, 794864233: 0}});

If it's not possible to set the quantity of an item to the requested value, because there is not enough of that item in stock, there will be a 422 error, and no quantity will be set as a result, not even the quantities of items that have sufficient stock.

If you use Line Item Properties you may end up with several items in the cart that share the same variant ID. How do you update the quantity of items in the cart when that happens? It turns out that you can also submit an array of numbers to /cart/update.js, where the size of the array will need to match the amount of line items in the cart.

Example, say you have 3 line items in the cart, with quantities 1, 2 and 3, and you want to change those quantities to 3, 2 and 1, you can use the following:

jQuery.post('/cart/update.js', {updates: [3, 2, 1]});

If there's any problem with updating any quantity when submitting an array of number, there will be a 422 error, and the quantities will remain the same as they were.

To change the quantity of one line item, you will need to use /cart/change.js instead (see the following section) and provide the 1-based index of the item in the cart like so:

jQuery.post('/cart/change.js', { line: 1, quantity: 1 });

To change the quantity of the second line item in the cart, you'll use this:

jQuery.post('/cart/change.js', { line: 2, quantity: 1 });

POST /cart/change.js

This call sets the quantity of an item already in the cart.

POST data

{

 quantity: 1,
 id: 794864053

}

Response The JSON of the cart.

If you use Line Item Properties you may end up with several items in the cart that share the same variant ID. How do you update the quantity of an item in the cart that has specific line item properties? Once you have identified the 1-based index of the item in the cart, you can use the line property instead of id like so:

{

 quantity: 1,
 line: 1

}

jQuery.post('/cart/change.js', { quantity: 1, line: 1 });

Caution

Although /cart/update.js and /cart/change.js may seem like they accomplish the same function, they truly are quite different. The /cart/update.js controller allows updates to several items at once, including items that may not yet be in the cart (it will add them), and it also allows updates of cart attributes and the cart note. The /cart/change.js controller is only able to update the quantity of one item at a time, and that item must be in the cart already. If the item is not in the cart, /cart/change.js will not add it and it will then return a 404 error. Whereas the /cart/update.js controller updates no quantity when any of the requested update cannot be met, the /cart/change.js controller, on the other hand, will adjust the quantity to add all items in stock if what is requested is greater than what's available. Use your browser's JavaScript console to test things out if you're not sure about the behavior of the different request URLs.

POST /cart/clear.js

This call sets all quantities of all line items in the cart to zero.

Response The JSON of an empty cart. This does not remove cart attributes nor the cart note.

Example:

{

 "token": "1d19a32178501c44ef2223d73c54d16d",
 "note": null,
 "attributes": {},
 "total_price": 0,
 "total_weight": 0,
 "item_count": 0,
 "items": [],
 "requires_shipping": false

}


You're building a quick order form? Beware Caution

Ajax requests that update the cart must be queued and sent synchronously to the server. Meaning: you must wait for your 1st ajax callback, to send your 2nd request, and then wait for its callback to send your 3rd request, etc.

Your request queue can be a very simple JavaScript array:

Spiffy.queue = [];

As you examine your quantity fields, you will add requests to that queue:

jQuery('.quantity').each(function() {

 Spiffy.queue.push( {
   variantId: jQuery(this).data('variant-id'),
   quantity: parseInt(jQuery(this).val(), 10) || 0
 } );

});

When you are done, you start your engine, using for instance Spiffy.addItem.

The callback of this Ajax request should call a function that shifts (removes) a request from Spiffy.queue and then call Spiffy.addItem with the variantId and quantity stored in the next request. Of course, you'll check if the queue has any requests left in it. If it's empty, you must cheerfully redirect to the cart page.

Something like this:

Spiffy.moveAlong = function() {

 // If we still have requests in the queue, let's process the next one.
 if (Spiffy.queue.length) {
   var request = Spiffy.queue.shift();
   Spiffy.addItem(request.variantId, request.quantity, Spiffy.moveAlong);
 }
 // If the queue is empty, we will redirect to the cart page.
 else {
   document.location.href = '/cart';
 }

};

Spiffy.moveAlong must be called within the callback of each Ajax request.