# Integrate the player

## Initial setup

To show the live events on your website you will have to add a customizable code on the page where you want to see the events. Then link the add to cart button to your website.

### *Set up the tag to display your live events* <a href="#sptag" id="sptag"></a>

Let's start with the tag. You can select the attributes in the Customizable Properties listed below to activate different features. You need to replace the `store-id's` value with the one given to you during the onboarding.

```html
<script async type="module" src="https://landing.ls.skeepers.io/live-shopping-landing.es.js"
></script>

<skp-landing 
  store-id="XXXXX"
	display-type= "all"
	transaction-type= "addToCart"
	staging=false
></skp-landing>

<style>
  :root {
    --skp-primary-color: #121212;
  }
</style>
```

{% hint style="info" %}
**You can insert this code:**&#x20;

In the \<head> tag&#x20;

In the \<body> tag
{% endhint %}

**Implement the widget in a Tag Manager**

In some cases, you won't be able to integrate the tag above in a Tag Manager. It will raise an error. As a workaround, use this tag:

```html
<!-- Create a container for your widget -->
<div id="container"></div>

<!-- Load the script -->
<script async type="module" src="https://landing.ls.skeepers.io/live-shopping-landing.es.js"></script>

<!-- Create the widget programatically -->
<script type="text/javascript">
    // Create the widget
    const widget = document.createElement('skp-landing');
    // Add the attributes
    widget.setAttribute('store-id', 'XXXXX');
    widget.setAttribute('display-type', "all");
    widget.setAttribute('transaction-type', "addToCart");
    widget.setAttribute('staging', false);
    widget.setAttribute('refresh-on-close', false);
    widget.setAttribute('should-display-preview', true);
    // Append it to the container created above
    document.querySelector('#container').appendChild(widget);
</script>

<script type="text/javascript">
    const styles = document.createElement('style');
    styles.type = "text/css";

    styles.innerHTML = `
    :root {
      --skp-primary-color: #000000;
    }
    `;
    document.head.appendChild(styles);
</script>

```

Here is an example once the tag is integrated

<figure><img src="/files/KRbpY63ysQTcUihCXe50" alt=""><figcaption><p>Display your live events on desktop</p></figcaption></figure>

<figure><img src="/files/sNvaNi17Krq8vl2eFa2M" alt=""><figcaption><p>Display your live events on mobile</p></figcaption></figure>

Your live events have 4 different states:

* **Upcoming** → The live is planned for an upcoming date. The days remaining will be displayed until 24 hours before the live, then a countdown will appear. Users can also add this event to their calendar or register to be notified by SMS (Option). When the countdown reaches 00:00:00 it will be replaced with the button “Watch the live”.
* **Live** → Users can now click “Watch the live” to open the player then browse the products, use the chat, make purchases… The splash screen video will be displayed until your broadcast starts.
* **In review** → Your live is over, you submitted it to review. You can now review your video and publish it from the web back office
* **Replay** → Your live has been reviewed, it is now available for everyone to watch. The chat is disabled but users can still read the comments made during the live.

### Customizable properties

<table data-header-hidden><thead><tr><th></th><th width="466.3333333333333"></th><th></th></tr></thead><tbody><tr><td><strong>Property</strong></td><td><strong>Description</strong></td><td><strong>Type</strong></td></tr><tr><td><code>store-id</code></td><td>Use your store id provided by Skeepers</td><td>String</td></tr><tr><td><code>display-type</code></td><td><code>"all"</code>: Display all your live shopping event<br><br><code>"upcoming"</code>: Display upcoming and live events<br><br><code>"archived"</code>: Display events in replay<br><br><code>"one"</code>: Display a specific event by adding <code>broadcast-id : [id]</code> under the displayType<br><br><code>"pdp"</code>: Use it with the <code>product</code> attribute. See our PDP integration<br><br><code>"none"</code>: Use it with our API integration</td><td>String</td></tr><tr><td><code>staging</code></td><td><code>true</code>: Use it for your testing environment. Display the broadcasts set with <code>staging: true</code> and <code>staging: false</code><br><br><code>false</code>: Use it for your production environment. Display the broadcasts set with <code>staging: false</code></td><td>Boolean</td></tr><tr><td><code>transaction-type</code></td><td><code>"addToCart"</code>: Displays an "Add to cart" button in the player. You will have to set up the add to cart<br><br><code>"linkToProductPage"</code>: Displays an "Open product page" button. Open the product's page in the same page if you are in the same domain. Open in a new tab if in another domain.<br><code>"customLinkToProductPage"</code>: Listen to our event to custom how you open the link to the product page. See more details</td><td>String</td></tr><tr><td><code>keywords</code></td><td>Filter your events by keywords. Add the keywords set during the broadcast's creation / edition on the backoffice. Case sensitive.<br>Ex: <code>keywords="["Beauty","Makeup"]"</code></td><td>[String]</td></tr><tr><td><code>refresh-on-close</code></td><td><code>true</code>: Refresh the page when closing the player<br><br><code>false</code>: Doesn't refresh the page when closing the player</td><td>Boolean</td></tr><tr><td><code>product</code></td><td><code>abcd_123</code>: A Product Id used for your live event. Use it with the <code>display-type: "pdp"</code> attribute. See our PDP integration.</td><td>String</td></tr><tr><td><code>should-display-preview</code></td><td><code>true</code>: Display the preview of your live event directly in your landing page.<br><br><code>false</code>: Doesn't display the preview of your live event. Keeps your live shopping image instead.</td><td>Boolean</td></tr><tr><td><code>picture-in-picture-mode</code></td><td><code>"default"</code>: Picture In Picture is activated and we can navigate across the whole website with the video.<br><br><code>"partial"</code>: Picture In Picture is activated on the landing page. The viewer can't navigate elsewhere.<br><br><code>"disabled"</code>: Picture In Picture is deactivated.</td><td>String</td></tr><tr><td><code>close-iframe-on-close-sp</code></td><td><code>true</code>: Close the iframe when closing the player. Works with <code>picture-in-picture-mode: "default"</code> or <code>picture-in-picture-mode: "partial"</code>.<br><br><code>false</code>: Stay in the page when closing the player.</td><td>Boolean</td></tr></tbody></table>

## Add to cart <a href="#addtocart" id="addtocart"></a>

To enable viewers to do an add-to-cart from a live, you need to set up a small code snippet with your software developer(s).

When using the `transaction-type: "addToCart"`, the player displays an add-to-cart button. You will have to set up your add-to-cart system by listening to the `skp:addToCart` event emitted by the button once it's clicked.

You can use this event to add your own tracking on each add-to-cart coming from the player. This way you can track add to cart done during a live or a replay all the way to your checkout.

```javascript
window.addEventListener('skp:addToCart', (event) => {
 	 const { origin, product } = event.detail
    console.log('origin', origin);
    console.log('product', product);

    addProductToCustomerCart(product);  // Replace it with your own add to cart implementation
    
    sendTrackingToYourPlatform(origin, product);  // Replace it with your own tracking solution
}) 
```

Product information comes from your product feed. Check the product ID in the product feed, it must be the same one used by your ecommerce platform.

### Shopify

```js
	const addToCartHandler = (event) => {
	const { product } = event.detail;
	const form = new FormData();
	form.append('quantity', 1);
	form.append('form_type', 'product');
	form.append('id', product.id);
    
  fetch(window.Shopify.routes.root + 'cart/add', 
		{
			method: 'POST',
			body: form,
			headers: {
				accept: 'application/javascript'
			},
	}).then(response => {
		return response.json();
	}).then(response => {
		// You could integrate your tracking for example
	}).catch((error) => { console.error('Error:', error); });
}

window.addEventListener('skp:addToCart', addToCartHandler);
```

{% hint style="info" %}
If you are using Shopify you can also install our Shopify App to easily integrate Live Shopping. More information [here](/features/shopify-app.md)
{% endhint %}

### SalesForce Commerce Cloud

```js
const addToCartHandler = (event) => {
	const { product } = event.detail;
	
    const productId = product.parentId || product.id;
    const variantId = product.id;

    const siteName = `Sites-YOUR_SITE`;
    const lang = `YOUR LANG`;
    
    return fetch(`/on/demandware.store/${siteName}/${lang}/Cart-AddProduct`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
      body: `pid=${productId}&quantity=1`,
    })
      .then(res => common.formatTrackingProductDatas(data))
      .catch((error) => { console.error('Error:', error); });
  }
  
  window.addEventListener('skp:addToCart', addToCartHandler);
```

### Hybris

```js
const addToCartHandler = (event) => {
    const { product } = event.detail;
	
    const productId = product.parentId || product.id;
    const variantId = product.id;
    
    return fetch('/cart/add', {
      headers: {
        accept: 'text/html, */*; q=0.01',
        'accept-language': 'fr-FR,fr;q=0.9,de;q=0.8,en-US;q=0.7,en;q=0.6',
        'content-type': 'application/x-www-form-urlencoded',
        'x-requested-with': 'XMLHttpRequest',
      },
      body: `productCode=${variantId}&quantity=1`,
      method: 'POST',
      mode: 'cors',
      credentials: 'include',
    })
      .then(() => fetch('/mini-cart/refresh?reloadCart=true', { method: 'GET' }))
      .catch((error) => { console.error('Error:', error); });
};

window.addEventListener('skp:addToCart', addToCartHandler);
```

### Magento

```js
const addToCartHandler = (event) => {
    const { origin, product } = event.detail;

    const addProductToCart = (product) => {
        const formKey = getCookie("form_key");
        const addToCartUrl = createAddToCartUrl(product.id);
        const postUenc = encodeUenc(addToCartUrl);
        fetch(addToCartUrl, {
            body: JSON.stringify({
                form_key: formKey,
                product: product.id,
                // You may need to add other attributes 
            }),
            method: 'POST',
            async: false
        }).catch((error) => { console.error('Error:', error); });
    };

    const createAddToCartUrl = (productId) => {
        let location = window.location.host;
        if (!location.endsWith("/")) location += "/";
        const currentLocationUENC = encodeURIComponent(encodeUenc());
        
        // You may need to create a dedicated endpoint for the skeepers Add To Cart
        const postUrl = location + "cart/add/uenc/" + currentLocationUENC + "/product/" + productId;
        return postUrl;
    };

    const encodeUenc = (value) => {
        const regex = /=/gi;
        return btoa(value).replace(regex, ",");
    };

    const getCookie = (cookieName) => {
        const cookies = document.cookie.split(";");
        for (let i = 0; i < cookies.length; i++) {
            const cookie = cookies[i].trim();
            if (cookie.startsWith(`${cookieName}=`)) {
                return cookie.substring(cookieName.length + 1);
            }
        }
        return null;
    };

    addProductToCart(product);
});

window.addEventListener('skp:addToCart', addToCartHandler);
```

### WooCommerce

```js
const addToCartHandler = (event) => {
    const { product } = event.detail;
    fetch(woocommerce_params.ajax_url, {
            body: JSON.stringify({
                'action': 'woocommerce_add_to_cart',
                'product_id': product.id,
                'quantity': 1
            }),
            method: 'POST',
            async: false
        }).catch((error) => { console.error('Error:', error); });
});

window.addEventListener('skp:addToCart', addToCartHandler);
```

## Style customization

In the style part of the script, you can add elements to customize how your live are displayed.

```html
<!-- Add your custom fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;500;600&display=swap" rel="stylesheet">

<script async type="module" src="https://landing.ls.skeepers.io/live-shopping-landing.es.js"
></script>

<skp-landing 
  store-id="XXXXX"
	display-type= "all"
	transaction-type= "addToCart"
	...
></skp-landing>

<style> 
  :root {
    --skp-radius: 5px;
    --skp-font-family: 'Nunito'; /* With your custom font */
    --skp-primary-color: #121212;
    --skp-text-color: #2f2e2e; 
    --skp-wrapper-color: #ffffff;
  }
</style>
```

<table data-header-hidden><thead><tr><th width="249"></th><th width="381.33333333333326"></th><th></th></tr></thead><tbody><tr><td><strong>Property</strong></td><td><strong>Description</strong></td><td><strong>Type</strong></td></tr><tr><td><code>--skp-radius</code></td><td>The border radius of the events cards</td><td>in px</td></tr><tr><td><code>--skp-font-family</code></td><td>Change the font for the title, description and CTA</td><td>String</td></tr><tr><td><code>--skp-primary-color</code></td><td>Color of the main button, on the landing page and the video player</td><td>#000000</td></tr><tr><td><code>--skp-text-color</code></td><td>Color of the title and description texts</td><td>#000000</td></tr><tr><td><code>--skp-wrapper-color</code></td><td>Event cards background color</td><td>#000000</td></tr></tbody></table>

## Link to the product page <a href="#customlinktoproductpage" id="customlinktoproductpage"></a>

The `transaction-type: "linkToProductPage"` or `transaction-type: "customLinkToProductPage"` will display an action button to redirect the client to the product's page instead of the add to cart.

### linkToProductPage

It will open a new tab to the product's page. It can open a link on another domain.

If the Picture in Picture mode is activated, the player will be instead reduced so that viewers can still browse your website while watching the live. More info on Picture in Picture

### customLinkToProductPage

If you need to implement your own redirection system, you will need to listen to the `skp:ls:openProductLink` emitted by the tag.

```js
window.addEventListener('skp:ls:openProductLink', (event) => {
    const { product, broadcast } = event.detail
    // Insert your add to card, tracking code here or any actions you want to happen
})
```

Product information comes from your product feed. Check the product ID in the product feed, it must be the same one used by your ecommerce platform.

## Autoplay

Instead of the customer manually starting the show, the player can be configured to automatically start when they land on your page.

Add the query parameter `?autoplay=liveId` to the URL where you have your list of live events displayed. You can share that URL with your customers, if that live is ongoing or in replay, the player will automatically be opened when opening the page.

Example: `http://www.yourwebsite.com/live-shopping?autoplay=964`

{% hint style="info" %}
You can find the ID of a live in the back office or the app on the edition screen of the corresponding event
{% endhint %}

## Keywords

Add keywords to your live events during creation or edition and add them in the widget to display the list of corresponding events. You can put as many keywords as you want.

Add the parameter `keywords= "['A','B','...']",` in the tag. Check the example below:

```javascript
<script async type="module" src="https://landing.ls.skeepers.io/live-shopping-landing.es.js"
></script>

<skp-landing
  store-id="XXXXX"
	keywords="['keyword1','keyword2']"
></skp-landing>
```

## Picture in Picture (PiP)

The player can be reduced to let your viewers browse your website while watching the live with no interruption. Viewers can click on maximize to reopen the main player at any time.

PiP mode might not work on every website. If you want to change the way it behaves, change the value of "picture-in-picture-mode" in the tag.

```javascript
<script async type="module" src="https://landing.ls.skeepers.io/live-shopping-landing.es.js"
></script>

<skp-landing
  store-id="XXXXX"
	picture-in-picture-mode= "partial"
></skp-landing>
```

## API Integration

If you want to fully control how to display and open your live you can use our API.

Change the tag value to `display-type= "none"` will load our SDK on the current page without interfering with your code. You can now, with the code below, launch the video player with any of your custom designs.

```html
<button id="cta-broadcast">Click To open Broadcast</button>

<script>
window.addEventListener('skp:ls:loaded', (event) => {
    const detail = event.detail
    console.log("@debug:skp:ls:loaded", detail);
  
    const {
      displayType,
      broadcasts
    } = detail;

    const $buttonBroadcast = document.getElementById('cta-broadcast');
    // Open a Shopping Party (You can call this method with every Mode)
    $buttonBroadcast.addEventListener('click', (e) => {
      e.preventDefault();
      e.stopPropagation();
      const openSPEvent = new CustomEvent('spockeeOpenShoppingParty', {
        detail: {
          id:${BROADCAST_ID},
          time:${YOUR_TIME},
        }
      });
      window.dispatchEvent(openSPEvent);
    })
  })
</script>
```

The parameter of the openShoppingParty method is an object with the following attributes:

* **id**: ID of your live event
* **time**: Enter a time in seconds to open a replay to a specific moment

Specify the `brodcastId` you received with our API

To display the list of live events, use the endpoint: `/v3/public/broadcasts`

## Open a live from a product detail page (PDP) <a href="#pdp" id="pdp"></a>

You can set our tag on a product page that can display a replay only if the specified product was highlighted during a live

This action will open the most recent live at the time the product was highlighted

This integration doesn't have any graphic interface, you need to create your own components to open the replay.

### How to install

* Add the tag on your product page (no DOM modification will be made, it will only load the Live Shopping widget
* Change the `display-type` to `pdp`
* Add the `product-id` attribute with the product ID
* Create a web component to open the video player

```javascript
<script async type="module" src="https://landing.ls.skeepers.io/live-shopping-landing.es.js"
></script>

<skp-landing 
  store-id="XXXXX"
	display-type= "pdp"
	product-id= "XXXXXX"
	transaction-type= "addToCart"
	staging= "false"
></skp-landing>

<style>
  :root {
    --skp-primary-color: #121212;
  }
</style>
```

### Button integration example

```html
<button id=“cta-pdp” style=“display: none”>See the product presentation</button>
<script>
  window.addEventListener('skp:ls:loaded', (event) => {
    const detail = event.detail
    console.log("@debug:skp:ls:loaded", detail);
    
    const {
      displayType,
      broadcasts
    } = detail;
    
    if (!!broadcasts.length) {
      // Display a button
      const buttonPDP = document.getElementById('cta-pdp');
      buttonPDP.style.display = 'block';
      buttonPDP.addEventListener('click', (e) => {
        e.preventDefault();
        e.stopPropagation();
        const openSPEvent = new CustomEvent('spockeeOpenShoppingParty');
        window.dispatchEvent(openSPEvent);
      });
    }
  })
</script>
```

\ <br>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://wiki.ls.skeepers.io/overview/integrate-the-player.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
