Skip to content

How to integrate a html web story carousel on your website

This guide explains how to embed the Slidy Story Carousel into your application, configure its behavior, and correctly handle user consent for analytics and personalization.

⚠️ Important! This guide assumes the reader has a technical background.

Basic Integration

Minimal Embed Example

<div
        class="cutnutwidget"
        id="wamRUXg0OV"
        style="min-height: 250px; padding: 10px 0 35px 0; position: relative;"
></div>
<script async defer src="https://widget.zazuapp.co/widget.js"></script>

Widget Configuration

The widget can be configured using HTML data-* attributes.
These options allow control over which stories are displayed, personalization behavior, and analytics handling.

Full Configuration Example


<div
        class="cutnutwidget"
        id="wamRUXg0OV"
        data-user-id="12345"
        data-story-ids="aaa,bbb"
        data-excluded-story-ids="ccc,ddd"
        data-content-ids="abc,def,ghi"
        data-excluded-content-ids="xyz,123"
        style="min-height: 250px; padding: 10px 0 35px 0; position: relative;"
></div>
<script async defer src="https://widget.zazuapp.co/widget.js"></script>

User Identification

data-user-id

A known user identifier that can be passed to the widget at runtime.

Behavior

  • Used for Google Analytics tracking if analytics consent is enabled

Example

data-user-id="12345"

Story Inclusion

data-story-ids

Comma-separated list of story IDs.

Behavior

  • Only these stories are shown
  • Stories are rendered in the exact order provided
  • Overrides personalization and content-based selection
  • Exclusions are still applied

Example

data-story-ids="aaa,bbb"

Story Exclusion

data-excluded-story-ids

Comma-separated list of story IDs to exclude.

Behavior

  • Always applied
  • Has priority over included story IDs
  • Removes matching stories in all cases

Example

data-excluded-story-ids="ccc,ddd"

Content-Based Selection

data-content-ids

Comma-separated list of content IDs.

Behavior

  • Used only if data-story-ids is not provided
  • Shows only stories matching these content IDs
  • Order follows the attribute order
  • If multiple stories share the same content ID, the first one wins
  • Exclusions are still applied

Example

data-content-ids="abc,def,ghi"

Content Exclusion

data-excluded-content-ids

Comma-separated list of content IDs to exclude.

Behavior

  • Always applied
  • Has priority over included content IDs
  • Removes matching stories in all cases

Example

data-excluded-content-ids="xyz,123"

Selection Logic

The widget resolves stories using the following logic:

  1. If story IDs are provided
    → Only those stories are rendered (ordered)

  2. Else, if content IDs are provided
    → Only stories matching those content IDs are rendered

  3. Else, if personalization is enabled and consent is given
    → Stories are reordered dynamically

  4. Else
    → Default editor order is used

Exclusions are applied in all cases.

Exclusion Rules

  • Story exclusions match against story.id
  • Content exclusions match against story.contentId
  • Exclusions always override inclusion rules

Notes & Edge Cases

  • Duplicate IDs are ignored (first occurrence wins)
  • Empty or invalid IDs are skipped
  • All ID comparisons are string-based and trimmed

Quick Recommendations

  • Use data-story-ids for full manual control
  • Use data-content-ids for group-based control
  • Use exclusion attributes to force-remove content
  • Personalization is used only when no include lists are provided

The widget includes a built-in Consent Manager that controls analytics and personalization behavior.
No widget code changes are required—only consent signals from your site or CMP.

The widget may:

  • Send Google Analytics events
  • Decorate outgoing URLs
  • Use personalization logic

If no consent is provided:

  • Analytics are disabled
  • Personalization is disabled
  • Analytics — controls tracking and analytics behavior
  • Personalization — controls content ordering and future customization features

Default widget namespace:

slidy_carousel

The widget can receive consent from:

  • Custom DOM events
  • postMessage (iframe-based CMPs)
  • Data layer pushes (GTM / Tealium)
  • TCF 2.x (__tcfapi)
  • Global Privacy Control (GPC)

Only one method is required.

<script>
    window.dispatchEvent(new CustomEvent(
      "slidy_carousel:consent_update",
      {
        detail: {
          analytics: true,
          personalization: false
        }
      }
    ));
</script>

postMessage (CMP in iframe)

parent.postMessage({
  ns: "slidy_carousel",
  type: "CONSENT_APPLY",
  payload: { analytics: true, personalization: false }
}, "*");

Widget acknowledgement:

{
  "ns": "slidy_carousel",
  "type": "slidy_carousel:CONSENT_ACK"
}

Data Layer Integration (GTM / Tealium)

<script>
    window.dataLayer = window.dataLayer || [];
    window.dataLayer.push({
      event: "slidy_carousel:consent_update",
      analytics: true,
      personalization: false
    });
</script>

TCF 2.x Integration (Automatic)

If window.__tcfapi is available, the widget automatically maps IAB purposes:

  • Analytics → purposes 1,7,8,9,10
  • Personalization → purposes 1,3,4,5,6,11

CMP signals always override TCF decisions.

For details on TCF purposes, please refer to:
👉 TCF Translations

Global Privacy Control

If the browser sends a GPC signal:

  • Analytics are disabled
  • Personalization is disabled

No configuration is required.

  • GPC overrides everything
  • CMP signals override TCF
  • Default state disables analytics and personalization

Storage & Data Handling

Stored in both:

  • Local Storage: slidy_carousel
  • Cookie: slidy_carousel

Deleting both resets the consent state.

Seen Stories Storage

Stored per widget instance:

slidy_carousel:{widgetKey}

Used only in the browser unless personalization consent is enabled.

AMP Story Consent

AMP stories require additional consent handled by AMP itself.

Stored under:

amp-story-state
amp-store:{DOMAIN}

Default domain:

https://stories.zazuapp.co

Troubleshooting

  • Verify the namespace matches slidy_carousel
  • Ensure consent values are booleans, not strings

Analytics cookies remain after disabling

  • The widget stops sending data
  • Cookie deletion must be handled by your CMP