Shopware: Landingpage outside of Shopware and “add to cart”

First things first: Don’t. This is a bad idea, because it lacks tracking, cookie consent and most likely more things, you just get for free if you implement either just a nice landing page inside of Shopware or if you need more liberty have your own controller and template (with all the benefits, like extending the base template).

But assuming you have a good reason (or didn’t know better), here is a way to implement API access from the landing page.

The examples only work if you are on the same site and even same vhost/machine. First we make sure to be on the same site, this fixes issues like missing www. subdomain or http/https.

if($_SERVER['SERVER_NAME'] !== 'www.example.com') {
    header('Location: https://www.example.com/smile-with-us/', true, 301);
    die();
}

The next step is to make sure to be able to add to cart via API. For this we need two things:

  1. The Storefron API key (which can be obtained from the backend)
  2. The sw-context-token of the customer. This token is automatically generated if you use the API, but this doesn’t help us if we want to have the same token during API call, so we set it. The session_name() of Shopware is “session-” and we create a session (we are on the same machine/vhost!) and set the sw-context-token.
session_name('session-');
session_start();
if (!isset($_SESSION['_sf2_attributes']['sw-context-token'])) {
    $_SESSION['_sf2_attributes']['sw-context-token'] = generateRandomString();
}

Once this is all done, we can set the token in JS as a variable and use it for alle the API call.

<script>
    const context = <?php echo json_encode($_SESSION['_sf2_attributes']['sw-context-token'], JSON_THROW_ON_ERROR)?>;
</script>

And then we can implement our own JS function and with the product id add products to the cart.

<button class="button" onclick="addToCart('0a725ef881cc4eab90e666de247fd038')">
    <span>In den Warenkorb</span>
</button>

For completeness here the JS function with the API call(s). And this is the reason we need to make sure that we are same-site. If not the API calls fail.

const accessKey = 'SWPPPPAV1111MQQQQHHHH9999';

function addToCart(productId) {
    // Create cart
    const data = null;

    const xhr = new XMLHttpRequest();
    xhr.withCredentials = true;

    xhr.addEventListener("readystatechange", function () {
        if (this.readyState === this.DONE) {

            // Add to cart
            const data = JSON.stringify({
                "items": [
                    {
                        "type": "product",
                        "referencedId": productId,
                        "quantity": 1
                    }
                ]
            });

            const xhr = new XMLHttpRequest();
            xhr.withCredentials = true;

            xhr.addEventListener("readystatechange", function () {
                if (this.readyState === this.DONE) {
                    location.href = 'https://www.example.com/checkout/cart/';
                }
            });

            xhr.open("POST", "https://www.example.com/store-api/checkout/cart/line-item");
            xhr.setRequestHeader("Content-Type", "application/json");
            xhr.setRequestHeader("Accept", "application/json");
            xhr.setRequestHeader("sw-access-key", accessKey);
            xhr.setRequestHeader("sw-context-token", context);

            xhr.send(data);
        }
    });

    xhr.open("GET", "https://www.example.com/store-api/checkout/cart");
    xhr.setRequestHeader("Content-Type", "application/json");
    xhr.setRequestHeader("Accept", "application/json");
    xhr.setRequestHeader("sw-access-key", accessKey);
    xhr.setRequestHeader("sw-context-token", context);

    xhr.send(data);
}

Hope this helps someone! 🙂

One thought on “Shopware: Landingpage outside of Shopware and “add to cart”

Leave a Reply