Integrating a Retail POS System with Snipcart's E-Commerce Platform

A client comes up to you and says:

I’d like to start selling online with my business.

As a developer, you automatically start thinking about a plethora of technical solutions. Your client keeps going:

I’d like both the online store and my retail stores to share one synchronized inventory.

You eliminate a bunch of solutions on the spot. But she’s not done yet:

Oh, and could you make sure my stores’ registers are directly connected to that inventory?

Interesting.

This was the technical challenge the smart folks at OPTION, a killer interactive marketing agency from Québec, brought to my door. OPTION has been crafting and deploying high-performing marketing strategies for local & international clients since 2008. Thanks to their client's unique needs, I had the opportunity to work on an innovative omni-channel commerce solution and test Snipcart's e-commerce integration flexibility.

Like many others, their client's SMB wanted to innovate technologically and save money while doing so. So how do you ship such an ambitious e-commerce project without exploding its budget? By adopting a modular approach, and asking the right questions:

Do we really need to build a new register, or will the existing one do? Do we need something heavy like WooCommerce? Or do we need to connect something complex like Magento to a more or less adapted inventory system?

POS, website & shopping cart: an omni-channel solution

For us at OrbiteWeb, it was Snipcart that tied everything together. Fostering modular approaches with its API & webhooks, Snipcart allowed us to craft a simple answer to the previous questions. Here are the components we bundled into a custom solution for OPTION and its client:

  • A RESTful API centralized inventory management system, complete with an admin panel to manage products, categories, sales, stocks, etc.
  • An API-connected point of sale (POS) system to sell in retail stores.
  • A website, connected to the API, displaying the products.

The beauty of it? You can develop such a set up in your favorite programming language. You could’ve built the API with PHP/Laravel, the POS with ReactJS, the website with WordPress. Whatever works, really! As for us, we used Laravel 5 for the API, the POS and the admin panel, and WordPress for the online shop.

Integrating Snipcart on the website

So where does Snipcart come in, you ask? Remember that simple WordPress website we mentioned? Like I said, our different products were already listed on it thanks to the RESTful API. All that was left to do then was to:

  1. Include Snipcart’s .js file on the website and;
  2. Create a buy button with simple HTML product attributes for each product.

Challenges we faced integrating the shopping cart

Adding multiple products at once

On specific pages, we had to be able to add two products to the cart with a single click. When a customer would buy a tennis racket, for instance, he'd need to be offered to select his preferred racket string, and ask for an in-store installation before the order's shipped. But strings could also be bought separately, in their related product category. In short, a customer had to be able to add both a racket + some strings to his shopping cart at the same time.

Out of the box, Snipcart didn't support this use case. At first, thinking about coming up with a solution on my own made me a bit anxious. My first reflex isn't always to get in touch with a product's support team: most times, I tend to try and solve problems myself. I tried to do just that. It didn't work.

So I did contact Snipcart's technical support team. Since I'm writing on this blog today, I must admit things went well between us! The team quickly understood my needs and even provided a way to handle this scenario. The fix: a new API call accepting an array of products:

Snipcart.api.items.add([{
    "id": "SMARTPHONE",
    "name": "Smartphone",
    "description": "",
    "url": "/",
    "price": 399.00,
    "quantity": 2,
    "stackable": true,
    "customFields": [{
        "name": "Memory size",
        "options": "16GB|32GB[+50.00]",
        "value": "32GB",
        "required": false
    }]
}, {
    "id": "BACON",
    "name": "Slice of bacon",
    "description": "",
    "url": "/",
    "price": 19.99,
    "quantity": 1,
    "stackable": true
}]);

An elegant solution, developed on their side in less than a week.

Defining custom product options stock

As we kept developing our project, another challenge popped up. Snipcart already handled the modification of product prices depending on selected custom fields.

data-item-custom2-options="Small|Medium[+5.00]|Large[+10.00]|Kid[-5.00]"

But I was wondering: could we also associate a specific stock to each of these custom product options? Unfortunately, the initial answer was no. However, it's a feature they've decided to prioritize following our discussions. It'll probably be something as straightforward as:

data-item-custom2-options="Small[id:5|stock:2]|Medium[id:6|stock:0]|Large[id:7|stock:4]"

The option with a stock value equal to 0 would be disabled. All in all, we've got some good news: the feature isn't available, but it will be. Other teams could've just refused to look into it.

But we still had to find a workaround for our project.

The idpart of the option is very important here: it’s what would allow us (via the webhook) to know which product variant was selected and should thus be subtracted.

To counter this problem, we came up with an original solution. Let’s throw in a bit of context first.

When adding a product to the cart, Snipcart asks for a product ID. Take men shoes for instance. Our inventory system sends this type of data for such a product:

{
  "id": 51,
  "title": "Speed Force",
  "brand": "Adidas",
  "model": "GH",
  "price": 109.99,
  "regular_price": 119.99,
  "special_price": 109.99,
  "stock": null,
  "options": [
    {
      "id": 21,
      "name": "Pointure",
      "values": [
        {
          "id": 494,
          "value": "8.5",
          "stock": 5
        },
        {
          "id": 495,
          "value": "9",
          "stock": 2
        },
        {
          "id": 496,
          "value": "9.5",
          "stock": 1
        }
      ]
    }
  ]
}

Suppose a visitor buys these shoes, size 9. Once the order is paid through Snipcart, the webhook must tell our API: product #51 with value #495 and option #21 has just been purchased. All of this so the accurate shoes quantity with the right size is removed from the inventory. So what was the solution? When adding a product to the cart, we send the product ID as well as other options and values in the following format: 51-21:495. A simple yet effective solution.

Quick bug fix

Towards the end of our development, a bug showed its ugly head. When trying to add two times a product with the same id, problems appeared. Infinite loading, no reaction, double product entry; that kind of annoying stuff. But the bug didn't trigger any of the previous anxiety anymore: I was more than happy to reach out to my new friends over at Snipcart and explain the problem. And they solved it, pronto.

Connecting Snipcart to the POS software & end-results

The set up we've put in place results in a simple, effective operation for OPTION's client. After a sale, Snipcart calls our API's webhook, which automatically subtracts stock quantities and sends an email invoice to the client.

If you want to check out the code behind this, I invite you to take a detailed look at this PHP gist right here:

Snipcart Webhook: Custom POS

And here's a sneak-peek of the final solution:

snipcart-pos-system-ecommerce-integration-store

Overview of the in-store retail POS [French].

snipcart-pos-system-ecommerce-integration-product

Overview of the POS product creation panel [French].

snipcart-pos-system-ecommerce-integration-inventory

Overview of the POS complete inventory panel [French].

Conclusion & feedback

Overall, integrating Snipcart was a pretty pleasant experience. However, in the spirit of transparency, I'd like to offer two last bits of feedback for the Snipcart geeks who helped me along! Here we go:

  • While the product documentation is a good, solid one, it could still be fully reviewed and augmented even more.
  • Error messages could use a higher level of specificity to help during tests and development.

But the good news is Snipcart's product is constantly improving. Their team pays an attentive ear to their users, and working with them is a lot of fun. By coupling the flexibility of their e-commerce solution and a custom POS software, we've set up the client with a powerful omni-channel commerce platform. The folks at OPTION then added their marketing magic on top of it, and soon enough, business was booming!

Again, I'd like to thank OPTION for the opportunity to work on such an ambitious, motivating technical challenge. You can follow them on Facebook to keep an eye on their projects. As for us, we'll be using Snipcart again for sure. :)


I’d love to answer any questions regarding how we set up Snipcart with the custom POS system. Got some? Just use the comments or shoot me an email. If you enjoyed this post, take a second to share it on Twitter. I’d really appreciate it!

Suggested posts: