> For the complete documentation index, see [llms.txt](https://docs.exoclick.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.exoclick.com/tutorials/tutorials/publishers-tutorials/dynamically-block-ad-types-for-exoclick-in-stream-zones.md).

# How to dynamically block ad types for ExoClick In-stream (video) zones

In this tutorial, we’ll demonstrate how to dynamically **block** ***Video (In-Stream)*** ad campaigns based on ad type.

This approach can be implemented across various scenarios, but a common application is to use this technique when you, as a publisher, want to show certain types of ads to users who provide consent, while blocking specific campaigns for those who don't accept your website's terms and conditions.

To illustrate this idea, we’ve created two code snippets using vanilla JS. In the first one, we demonstrate how to block video ads based on URL parameters. The second example simulates a case in which user consent is stored in the browser’s local storage. In both cases, we’re leveraging Exoclick’s `block-ad-types` feature.

In order to display In-Stream ads, we're using [Fluid Player](https://www.fluidplayer.com/), a free, open-source HTML5 player that is compatible with VAST and VPAID formats.

> Bear in mind that if you have a different setup, you will have to adapt this code to suit your player requirements. However, the core logic for the `block-ad-types` feature remains the same.

## EXAMPLE 1 - Block In-Stream ad types based on URL Parameter

This is a fairly straightforward logic that doesn't differ much from a basic Fluid Player integration, in which a standard video player is loaded first, and then Fluid Player is attached to it.

The main difference here is that, before attaching Fluid Player to the standard video player, we perform a URL parameter check, where we retrieve the value for `user_verified`.

With that defined, we have an if statement that sets the `dynamicVastTag` variable to either block NSFW ads for unverified users or allow all ads for verified users.

Once this variable is set, we proceed to load the Fluid Player config object, making sure to include the `dynamicVastTag` variable as a value for the `vastTag` property.

```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>In Stream (video) ads | block-ad-types</title>

    <!-- Import Fluid Player -->
    <script src="https://cdn.fluidplayer.com/v3/current/fluidplayer.min.js"></script>

    <!-- Initialize an instance of Fluid Player -->
    <script>
      console.log("initializing fluid")
      var player = fluidPlayer("example-player");
    </script>

  </head>

  <body>
    <h1>block-ad-types for In Stream (video) ads using URL params</h1>

    <!-- Regular <video> player -->
    <div class="video-wrapper">
      <video
        id="example-player"
        muted
        style="width: 50vw; height: 500px; margin: 0 auto; padding: 0"
      >
        <source
          src="http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4"
          type="video/mp4"
        />
        Your browser does not support the video tag.
      </video>
    </div>

    <!-- Script that sets Fluid Player config -->
    <script>
      
      // Function to get user_verified value from URL parameter
      const userVerified = new URLSearchParams(window.location.search).get(
        "user_verified"
      );

      // Define blocked ad types based on URL parameters
      let dynamicVastTag =
        "https://s.magsrv.com/v1/vast.php?idzone=5532704&block_ad_types=101"; // block NSFW ads
      if (userVerified === "1") {
        dynamicVastTag = "https://s.magsrv.com/v1/vast.php?idzone=5532704";  // if user is verified, show all ads
      }

      var player = fluidPlayer("example-player", {
        layoutControls: {
          primaryColor: "#FF0000",
          timelinePreview: {
            file: "thumbnails.vtt",
            type: "VTT",
          },
          controlForwardBackward: {
            show: true,
            doubleTapMobile: false,
          },
        },
        vastOptions: {
          adList: [
            {
              roll: "preRoll",
              vastTag: dynamicVastTag,
              timer: 5,
            },
          ],
        },
      });
    </script>
  </body>
</html>
```

## EXAMPLE 2 - Block In Stream ad types based on local storage data

This implementation differs from the previous one by using local storage to manage user consent instead of URL parameters. The code is modular, with separate functions for creating the video player and the Fluid Player configuration.

The `<head>` section of the HTML contains three main functions that control ad serving based on user consent:

* ***`insertVideoPlayer`*** creates a video player element and adds it to the webpage.
* ***`fluidPlayerConfig`*** generates a configuration object for Fluid Player. This function's key logic is in how it chooses the ad URL: if the user hasn't accepted the terms (false), it adds `&block_ad_types=101` to the URL to block certain ads. If the user has accepted (true), it uses the standard URL, allowing all ads.
* ***`insertFluidPlayer`*** ties everything together. It first creates the video player using insertVideoPlayer and then attaches Fluid Player to it, using the specific configuration from playerConfig that's tailored to the user's consent.

In the `<body>`, the final script checks local storage for user consent on page load and renders the players accordingly. If no consent was given but the user later accepts the terms by clicking the button, the player is reinitialized with the updated permissions.

```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />

    <title>In Stream (video) ads | block-ad-types</title>

    <!-- Import Fluid Player  -->
    <script src="https://cdn.fluidplayer.com/v3/current/fluidplayer.min.js"></script>

    <script>
      // Dynamically creates a <video> element and places it inside the div with the given ID parameter
      const insertVideoPlayer = (containerId) => {
        const videoPlayerContainer = document.getElementById(containerId);
        videoPlayerContainer.innerHTML = "";
        let video = document.createElement("video");
        video.id = "example-player";
        video.style.width = "700px";
        video.style.height = "500px";
        video.controls = true;

        let source = document.createElement("source");
        source.src =
          "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4";
        source.type = "video/mp4";

        video.appendChild(source);
        video.append("Your browser does not support the video tag.");

        videoPlayerContainer.appendChild(video);
      };
    </script>

    <script>
      // Defines the Fluid Player configuration, including the dynamic VAST tags that determine which ads to block or show based on user consent
      let fluidPlayerConfig = (acceptTerms) => {
        return {
          layoutControls: {
            primaryColor: "#FF0000",
            timelinePreview: {
              file: "thumbnails.vtt",
              type: "VTT",
            },
            controlForwardBackward: {
              show: true,
              doubleTapMobile: false,
            },
          },
          vastOptions: {
            adList: [
              {
                roll: "preRoll",
                vastTag: acceptTerms // User consent
                  ? "https://s.magsrv.com/v1/vast.php?idzone=5532704" // Show all ads
                  : "https://s.magsrv.com/v1/vast.php?idzone=5532704&block_ad_types=101", // Block NSFW ads
                timer: 5,
              },
            ],
          },
        };
      };
    </script>

    <!-- This is the script that binds the video player and Fluid Player logic and renders the content in the UI -->
    <script>
      let player;

      const insertFluidPlayer = (acceptTerms) => {
        insertVideoPlayer("video-wrapper");
        player = fluidPlayer("example-player", fluidPlayerConfig(acceptTerms));
      };
    </script>
  </head>

  <body>
    <h1>block-ad-types for In Stream (video) ads using local storage</h1>

    <button
      id="accept-terms-button"
      onclick="
      localStorage.setItem('userConsent', JSON.stringify(true));
      insertFluidPlayer(true);
      this.remove();
      "
    >
      Accept Terms
    </button>

    <!-- Container for the video player to attach to -->
    <!-- Must be defined before the Fluid Player initialization -->
    <div id="video-wrapper"></div>

    <!-- This script checks for the user consent in local storage and initializes the player accordingly -->
    <script>
      const userConsentCookie = localStorage.getItem("userConsent");
      const parsedCookie = JSON.parse(userConsentCookie);

      if (parsedCookie === true) {
        insertFluidPlayer(true);
        const consentButton = document.getElementById("accept-terms-button");
        if (consentButton) {
          consentButton.remove();
        }
      } else {
        insertFluidPlayer(false);
      }
    </script>
  </body>
</html>
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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 following URL with the `ask` and `goal` query parameters:

```
GET https://docs.exoclick.com/tutorials/tutorials/publishers-tutorials/dynamically-block-ad-types-for-exoclick-in-stream-zones.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `build a script that syncs our docs to a CMS` lets GitBook tailor the answer to that use case.

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.
