> ## Documentation Index
> Fetch the complete documentation index at: https://docs.permutive.com/llms.txt
> Use this file to discover all available pages before exploring further.

# YouTube

> Target audiences on YouTube.com using Google Ads remarketing via the Google tag

export const NoBadge = () => {
  return <span style={{
    display: 'inline-block',
    padding: '0.125rem 0.5rem',
    borderRadius: '0.25rem',
    fontSize: '0.625rem',
    background: '#F7D0E2',
    color: '#1A1A1A',
    fontWeight: '500'
  }}>
      No
    </span>;
};

export const YesBadge = () => {
  return <span style={{
    display: 'inline-block',
    padding: '0.125rem 0.5rem',
    borderRadius: '0.25rem',
    fontSize: '0.625rem',
    background: '#C7E8F9',
    color: '#1A1A1A',
    fontWeight: '500'
  }}>
      Yes
    </span>;
};

export const BadgeRowCenter = ({label, children}) => {
  return <div style={{
    display: 'flex',
    justifyContent: 'space-between',
    alignItems: 'center',
    marginBottom: '0.5rem'
  }}>
      <span style={{
    fontSize: '0.625rem',
    color: '#6b7280',
    textTransform: 'uppercase',
    fontWeight: '500',
    letterSpacing: '0.05em'
  }}>
        {label}
      </span>
      {children}
    </div>;
};

export const BadgeRow = ({label, children}) => {
  return <div style={{
    display: 'flex',
    justifyContent: 'space-between',
    alignItems: 'flex-start',
    marginBottom: '0.5rem'
  }}>
      <span style={{
    fontSize: '0.625rem',
    color: '#6b7280',
    textTransform: 'uppercase',
    fontWeight: '500',
    letterSpacing: '0.05em'
  }}>
        {label}
      </span>
      {children}
    </div>;
};

export const BadgeContainer = ({children}) => {
  return <div style={{
    display: 'flex',
    gap: '0.25rem',
    flexWrap: 'wrap',
    justifyContent: 'flex-end',
    minWidth: '0',
    flex: '1'
  }}>
      {children}
    </div>;
};

export const ProductRequiredBadge = ({product}) => {
  const getBadgeStyle = product => {
    switch (product) {
      case 'Core Platform':
        return {
          background: '#CB88FC',
          color: '#1A1A1A'
        };
        --purple;
      case 'Routing':
        return {
          background: '#CB88FC',
          color: '#1A1A1A'
        };
        --purple;
      case 'Contextual':
        return {
          background: '#CB88FC',
          color: '#1A1A1A'
        };
        --purple;
      default:
        return {
          background: '#A7B3D9',
          color: '#1A1A1A'
        };
        --haze;
    }
  };
  const style = getBadgeStyle(product);
  return <span style={{
    display: 'inline-block',
    padding: '0.125rem 0.375rem',
    borderRadius: '0.25rem',
    fontSize: '0.625rem',
    background: style.background,
    color: style.color,
    fontWeight: '500'
  }}>
      {product}
    </span>;
};

export const SdkRequiredBadge = ({required}) => {
  const getBadgeStyle = required => {
    switch (required) {
      case 'Yes':
        return {
          background: '#C7E8F9',
          color: '#1A1A1A'
        };
        --blue;
      case 'No':
        return {
          background: '#F7D0E2',
          color: '#1A1A1A'
        };
        --pink;
      default:
        return {
          background: '#A7B3D9',
          color: '#1A1A1A'
        };
        --haze;
    }
  };
  const style = getBadgeStyle(required);
  return <span style={{
    display: 'inline-block',
    padding: '0.125rem 0.375rem',
    borderRadius: '0.25rem',
    fontSize: '0.625rem',
    background: style.background,
    color: style.color,
    fontWeight: '500'
  }}>
      {required}
    </span>;
};

export const CapabilityBadge = ({capability}) => {
  const getBadgeStyle = capability => {
    switch (capability) {
      case 'Event Collection':
        return {
          background: '#EFDFC8',
          color: '#1A1A1A'
        };
        --clay;
      case 'Cohort Activation':
        return {
          background: '#EFDFC8',
          color: '#1A1A1A'
        };
        --clay;
      case 'Campaign Optimization':
        return {
          background: '#EFDFC8',
          color: '#1A1A1A'
        };
        --clay;
      case 'Identity Signal':
        return {
          background: '#EFDFC8',
          color: '#1A1A1A'
        };
        --clay;
      case 'Contextual Signal':
        return {
          background: '#EFDFC8',
          color: '#1A1A1A'
        };
        --clay;
      case 'Connectivity':
        return {
          background: '#EFDFC8',
          color: '#1A1A1A'
        };
        --clay;
      case 'Routing':
        return {
          background: '#EFDFC8',
          color: '#1A1A1A'
        };
        --clay;
      case 'Data Collaboration':
        return {
          background: '#EFDFC8',
          color: '#1A1A1A'
        };
        --clay;
      default:
        return {
          background: '#A7B3D9',
          color: '#1A1A1A'
        };
        --haze;
    }
  };
  const style = getBadgeStyle(capability);
  return <span style={{
    display: 'inline-block',
    padding: '0.125rem 0.375rem',
    borderRadius: '0.25rem',
    fontSize: '0.625rem',
    background: style.background,
    color: style.color,
    fontWeight: '500',
    whiteSpace: 'nowrap'
  }}>
      {capability}
    </span>;
};

export const EnvironmentBadge = ({environment}) => {
  const getBadgeStyle = environment => {
    switch (environment) {
      case 'Web':
        return {
          background: '#F9C1A8',
          color: '#1A1A1A'
        };
        --peach;
      case 'iOS':
        return {
          background: '#F9C1A8',
          color: '#1A1A1A'
        };
        --peach;
      case 'Android':
        return {
          background: '#F9C1A8',
          color: '#1A1A1A'
        };
        --peach;
      case 'CTV':
        return {
          background: '#F9C1A8',
          color: '#1A1A1A'
        };
        --peach;
      case 'API Direct':
        return {
          background: '#F9C1A8',
          color: '#1A1A1A'
        };
        --peach;
      case 'Realtime API':
        return {
          background: '#F9C1A8',
          color: '#1A1A1A'
        };
        --peach;
      default:
        return {
          background: '#A7B3D9',
          color: '#1A1A1A'
        };
        --haze;
    }
  };
  const style = getBadgeStyle(environment);
  return <span style={{
    display: 'inline-block',
    padding: '0.125rem 0.375rem',
    borderRadius: '0.25rem',
    fontSize: '0.625rem',
    background: style.background,
    color: style.color,
    fontWeight: '500',
    whiteSpace: 'nowrap'
  }}>
      {environment}
    </span>;
};

export const DirectionBadge = ({direction}) => {
  const getBadgeStyle = direction => {
    switch (direction) {
      case 'Bidirectional':
        return {
          background: '#FA8784',
          color: '#1A1A1A'
        };
        --tomato;
      case 'Destination':
        return {
          background: '#FA8784',
          color: '#1A1A1A'
        };
        --tomato;
      case 'Source':
        return {
          background: '#FA8784',
          color: '#1A1A1A'
        };
        --tomato;
      default:
        return {
          background: '#A7B3D9',
          color: '#1A1A1A'
        };
        --haze;
    }
  };
  const style = getBadgeStyle(direction);
  return <span style={{
    display: 'inline-block',
    padding: '0.125rem 0.375rem',
    borderRadius: '0.25rem',
    fontSize: '0.625rem',
    background: style.background,
    color: style.color,
    fontWeight: '500'
  }}>
      {direction}
    </span>;
};

<Card title="">
  <div style={{ display: 'flex', alignItems: 'center', marginBottom: '1rem' }}>
    <div style={{ width: '32px', height: '32px', marginRight: '0.75rem', display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
      <img src="https://mintcdn.com/permutive/pNhz39ducTVcQczh/images/integrations/logos/youtube.svg?fit=max&auto=format&n=pNhz39ducTVcQczh&q=85&s=6e88a7f65b7b4bd42f6c6b9cf8f4ef4b" alt="YouTube" style={{ maxWidth: '32px', maxHeight: '32px', display: 'block' }} width="24" height="24" data-path="images/integrations/logos/youtube.svg" />
    </div>

    <h3 style={{ margin: 0, fontSize: '1.125rem', fontWeight: '600' }}>YouTube</h3>
  </div>

  <div style={{ marginBottom: '1rem' }}>
    <BadgeRowCenter label="Direction">
      <DirectionBadge direction="Destination" />
    </BadgeRowCenter>

    <BadgeRowCenter label="Environment">
      <BadgeContainer>
        <EnvironmentBadge environment="Web" />
      </BadgeContainer>
    </BadgeRowCenter>

    <BadgeRowCenter label="Capability">
      <BadgeContainer>
        <CapabilityBadge capability="Cohort Activation" />
      </BadgeContainer>
    </BadgeRowCenter>

    <BadgeRowCenter label="SDK Required">
      <SdkRequiredBadge required="Yes" />
    </BadgeRowCenter>

    <BadgeRowCenter label="Product(s) Required">
      <ProductRequiredBadge product="Core Platform" />
    </BadgeRowCenter>
  </div>

  <p style={{ margin: 0, fontSize: '0.875rem', color: '#6b7280', lineHeight: '1.5' }}>
    Retarget your website visitors on YouTube.com by passing Permutive cohort membership into Google Ads remarketing audiences via the Google tag (gtag.js).
  </p>
</Card>

<CardGroup cols={2}>
  <Card title="Setup" href="#setup" icon="gear" />

  <Card title="Troubleshooting" href="#troubleshooting" icon="wrench" />
</CardGroup>

<Note>
  Looking to target ads in an embedded YouTube player on your website or app? See the [Embedded YouTube Player Integration](/integrations/video/youtube).
</Note>

## Overview

YouTube is the world's largest video platform. This integration enables targeting of Permutive cohorts on YouTube.com itself, using Google Ads remarketing built on the Google tag (gtag.js) and deployed through Google Tag Manager.

This integration is a Destination:

* **Destination:** Permutive cohort memberships are passed to Google Ads via a custom event on the Google tag, where they are used to build rule-based remarketing audiences in the publisher's own Google Ads account.

Use cases include:

* Retarget your website visitors with Permutive cohorts when they watch content on YouTube.com
* Extend audience reach for direct-sold and audience-extension campaigns that you run through your own Google Ads account
* Use the same cohort-based audiences to target Search and Gmail campaigns alongside YouTube

<Info>
  **How it works**

  YouTube ad targeting is based on the viewer's signed-in Google Account, not on publisher-side identifiers — cookies and key-values set on your own site cannot be matched to a YouTube viewing session directly.

  Google Ads remarketing solves this by having the Google tag (gtag.js), running on your site, record visits against Google's own identity signals. Google performs the match to signed-in Google accounts internally — the publisher passes no user IDs or PII. The `cohorts` event parameter sent alongside each visit determines which audience segments, defined as rules in Google Ads, that visit qualifies for.
</Info>

## Scope & limitations

* Designed for publishers with their own Google Ads account running their own direct-sold or audience-extension campaigns. Audiences live in your Google Ads account and are not available to third-party buyers or in DV360.
* Web environments only.
* Only signed-in Google users are matchable. In consent-regulated regions, remarketing lists populate only for users who have granted consent (Google Consent Mode).
* Audience lists build cumulatively and can take up to around 30 days to reach full scale. Google's minimum audience-size thresholds apply before a list is eligible to serve.
* Segment membership reflects the user's cohorts at the time of the visit and persists until the configured membership duration expires.
* All active cohort memberships are shared with Google Ads via the event.

## Environment Compatibility

| Environment | Supported | Notes |
| - | - | - |
| **Web** | <YesBadge /> | Via the Google tag (gtag.js), deployed through Google Tag Manager on your site |
| **iOS** | <NoBadge /> | Not supported via this method |
| **Android** | <NoBadge /> | Not supported via this method |
| **CTV** | <NoBadge /> | Not supported via this method |
| **API Direct** | <NoBadge /> | Not supported via this method |

## Prerequisites

* **Permutive Web SDK**: Deployed on your site, with cohorts computing client-side so that the `_psegs` localStorage key is populated.
* **Google Ads account**: Your own Google Ads account, used to create and target remarketing segments.
* **Google Tag Manager**: Used to deploy the variable and tag described in Setup below, or the ability to deploy the equivalent snippets directly in your page code.
* **Google Consent Mode**: Configured where consent regulations apply, so that remarketing lists populate correctly for users who have granted consent.

## Setup

<Tabs>
  <Tab title="Primary Setup Steps">
    <Steps>
      <Step title="Create a Custom JavaScript variable for Permutive cohorts">
        In Google Tag Manager, create a new **Custom JavaScript** variable (for example, named `Permutive Cohorts`) that reads the user's current Permutive cohort memberships from localStorage:

        ```javascript theme={"dark"}
        function() {
          try {
            return JSON.parse(window.localStorage.getItem('_psegs') || '[]');
          } catch (e) {
            return [];
          }
        }
        ```

        <Note>
          Reading localStorage directly is used here, rather than the SDK's `permutive.segments()` method, because GTM Custom JavaScript variables must return their value synchronously, whereas `permutive.segments()` is asynchronous. Elsewhere in our SDK documentation we recommend `permutive.segments()` for retrieving cohorts in your own code — this variable is the synchronous equivalent needed specifically for GTM. See [Cohorts and Activations](/sdks/web/javascript-sdk/core-concepts/cohorts-and-activations) for more on the `_psegs` key.
        </Note>
      </Step>

      <Step title="Create the Google tag and Permutive event Custom HTML tag">
        Create a **Custom HTML** tag in GTM that loads the Google tag (gtag.js) with your Google Ads conversion ID, and fires a custom `permutive` event carrying the cohorts variable as an event parameter:

        ```html theme={"dark"}
        <!-- Google tag (gtag.js) - Google Ads -->
        <script async src="https://www.googletagmanager.com/gtag/js?id=AW-XXXXXXXXX"></script>
        <script>
        window.dataLayer = window.dataLayer || [];
        function gtag(){dataLayer.push(arguments);}
        gtag('js', new Date());
        gtag('config', 'AW-XXXXXXXXX');
        </script>

        <!-- Permutive cohorts event -->
        <script>
        gtag('event', 'permutive', {
          cohorts: {{Permutive Cohorts}}
        });
        </script>
        ```

        Replace `AW-XXXXXXXXX` with your Google Ads conversion ID. If you have multiple Google Ads accounts, add one `gtag('config', ...)` line per account — the `permutive` event only needs to fire once.
      </Step>

      <Step title="Choose a trigger">
        Set the tag to fire on a trigger that runs after the Permutive SDK has executed on the page — **Window Loaded** is a reliable choice.

        Because Google Ads remarketing lists build cumulatively across visits, an occasional stale read is generally tolerable. Firing the tag after Permutive keeps the cohorts passed on each visit as fresh as possible.
      </Step>

      <Step title="Create rule-based segments in Google Ads Audience Manager">
        In **Google Ads Audience Manager**, create one rule-based "your data" (website visitor) segment per Permutive cohort you want to target. Each rule should match the `cohorts` event parameter containing the relevant cohort ID, with a configured membership duration (90 days is a reasonable starting point).

        See [Google's documentation on creating website visitor segments](https://support.google.com/google-ads/answer/2454064) for the exact steps in the Google Ads UI.
      </Step>

      <Step title="Target the segments in your campaigns">
        Add the segments you've created as audience targeting on your **YouTube**, **Search**, or **Gmail** campaigns in Google Ads.
      </Step>

      <Step title="Verify the setup">
        Use GTM Preview mode or Google Tag Assistant to confirm the Custom HTML tag fires on the expected trigger and the `permutive` event is sent. You can also inspect the network request made to Google Ads in your browser's developer tools and confirm the `cohorts` parameter is present with the expected cohort IDs.
      </Step>
    </Steps>
  </Tab>

  <Tab title="Web">
    YouTube.com targeting is configured entirely within Google Tag Manager and Google Ads. There is no additional web implementation required beyond:

    1. Having the Permutive SDK deployed on your website so cohorts are computed and written to the `_psegs` localStorage key.
    2. Deploying the Custom JavaScript variable and Custom HTML tag described in the Primary Setup Steps tab.

    All remaining configuration — creating segments and targeting them in campaigns — happens in the Google Ads interface.
  </Tab>
</Tabs>

## Data Types

With this integration configured, Permutive cohort membership is passed to Google Ads via a custom gtag event:

<AccordionGroup>
  <Accordion title="permutive (gtag event)">
    A custom event fired on the Google tag (gtag.js) whenever the Permutive Custom HTML tag runs, carrying the user's current cohort memberships to Google Ads.

    <ResponseField name="cohorts" type="array[string]">
      The full list of Permutive cohort IDs the user currently belongs to, read from the `_psegs` localStorage key. The complete array is passed as-is — no filtering is applied.
    </ResponseField>
  </Accordion>

  <Accordion title="_psegs (localStorage key)">
    The Permutive Web SDK localStorage key holding all of a user's current cohort memberships, as a JSON array of cohort ID strings. This is the source the GTM Custom JavaScript variable reads from. See [Cohorts and Activations](/sdks/web/javascript-sdk/core-concepts/cohorts-and-activations) for more detail on how this key is populated.
  </Accordion>
</AccordionGroup>

## Troubleshooting

<AccordionGroup>
  <Accordion title="Segment not populating">
    If a rule-based segment in Google Ads Audience Manager isn't building membership:

    * **Consent denied under Consent Mode**: For users in consent-regulated regions who haven't granted consent, visits aren't recorded against remarketing lists.
    * **Tag not firing**: Use GTM Preview mode to confirm the Custom HTML tag is firing on the page.
    * **Segment rule not matching the `cohorts` parameter**: Array values don't always surface cleanly in Google Ads segment rule matching. If your rule isn't matching reliably against the array, a fallback is to have the Custom JavaScript variable return a comma-joined string instead (`.join(',')` on the array) and match the segment rule against that string.
    * **Initial delay**: Newly created segments can take 24–48 hours to begin showing membership.
  </Accordion>

  <Accordion title="Lower-than-expected reach">
    If reach on YouTube, Search, or Gmail is lower than expected:

    * **\~30-day ramp**: Remarketing lists build cumulatively over time and can take up to around 30 days to reach full scale.
    * **Minimum list sizes**: Google enforces minimum audience-size thresholds before a list is eligible to serve.
    * **Signed-in users only**: Only visits from users signed into a Google Account can be matched — anonymous YouTube viewers can't be targeted.
  </Accordion>

  <Accordion title="Cohorts empty or stale when the tag fires">
    If the `cohorts` parameter is empty, or reflects an earlier visit:

    * **Trigger timing**: If the tag fires before the Permutive SDK has finished computing cohorts for the pageview, the `cohorts` parameter may be empty or stale. Move the trigger to fire later, for example on Window Loaded.
    * **SDK not deployed**: Confirm the Permutive Web SDK is present and running on the page.
    * **Check localStorage directly**: Open your browser's developer tools and inspect `localStorage._psegs` to confirm cohort IDs are present before the tag fires.
  </Accordion>

  <Accordion title="Verifying the tag fires correctly">
    To confirm the integration is working end-to-end:

    * Use GTM Preview mode or Google Tag Assistant to confirm the Custom HTML tag fires on the expected trigger, and check the `Permutive Cohorts` variable's output in Preview mode.
    * Inspect the network request made to Google Ads in your browser's developer tools (Network tab) and confirm the `cohorts` parameter is present with the expected cohort IDs.
  </Accordion>
</AccordionGroup>

## Changelog

<Info>
  For detailed changelog information, visit our [Changelog](https://changelog.permutive.com/).
</Info>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.