# Product Hydration

There will be instances when products need to display differently from the data registered in Firework CMS. Product information can be updated from your OMS but not synced to Firework CMS. Product availability may also change based on real-time data. You can pass the latest information to the Firework player using Product Hydration.

<figure><img src="https://688917408-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MLoGG8m6bokS9YTmS7m%2Fuploads%2Fgit-blob-dbd07a04d62c46a2c3cb6c58e469322220f4a560%2FProduct%20Hydration.png?alt=media" alt=""><figcaption></figcaption></figure>

### Provide Product Data

With the Firework Shopping API `onProductsLoaded` and `onWidgetProductsLoaded` you can provide a list of products to be updated on the player interface. Consider the scenario above where the title and the product price are different in the e-commerce platform, and you want to display the most up-to-date information about the product on the player. You can use the following code snippet to achieve it:

**Sample Code**

```javascript
// Helper method to convert a remote product to a Firework product object.
function buildFWProduct(remoteProduct) {
  const { id, name, variations } = remoteProduct;
  
  // Use `shopping.productFactory` to build Firework product object
  return window._fwn.shopping.productFactory((product) => {
    // 1. Update the product title.
    product
      .extId(id)
      .name(name);

    // 2. Update product variant price and availability.
    for (const remoteVariant of variations) {
      const { 
        variation_id, 
        is_in_stock, 
        display_price,
      } = remoteVariant;
      product.variant((variant) => {
        variant
          .extId(variation_id)
          .isAvailable(is_in_stock)
          .price(display_price)
      );
    }
  });
}

// Configure callback to hydrate the video product when the products are loaded.
// Fired for each video individually. Suitable for widgets rendering single video (fw-storyblock)
window._fwn.shopping.onProductsLoaded(async ({ products }) => {
  const productIds = products.map((product) => product.produce_ext_id);
  
  // Make a server request to get the latest product data.
  const remoteProducts = await fetchProductsFromServer(productIds);
  
  return remoteProducts.map((remoteProduct) => buildFWProduct(remoteProduct));
});
```

```javascript
// Alternativelly, widget level callback triggered as soon as all videos are loaded (or paginated).
// Suitable for widgets displaying multiple videos (fw-carousel, fw-player-deck)
window._fwn.shopping.onWidgetProductsLoaded(async ({ products }) => {
  const productIds = products.map((product) => product.produce_ext_id);
  
  // Make a server request to get the latest product data.
  const remoteProducts = await fetchProductsFromServer(productIds);
  
  return remoteProducts.map((remoteProduct) => buildFWProduct(remoteProduct));
});
```
