> ## 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.

# IBM Watson

> Integrate with IBM Watson for contextual data enrichment.

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;
      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/ibm-watson.svg?fit=max&auto=format&n=pNhz39ducTVcQczh&q=85&s=39d218a193f60151e264cb22872df7ad" alt="IBM Watson" style={{ maxWidth: '32px', maxHeight: '32px', display: 'block', backgroundColor: '#f3f4f6', borderRadius: '4px', padding: '2px' }} width="560" height="400" data-path="images/integrations/logos/ibm-watson.svg" />
    </div>

    <h3
      style={{
    margin: 0,
    fontSize: "1.125rem",
    fontWeight: "600",
  }}
    >
      IBM Watson
    </h3>
  </div>

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

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

        <EnvironmentBadge environment="iOS" />

        <EnvironmentBadge environment="Android" />
      </BadgeContainer>
    </BadgeRowCenter>

    <BadgeRowCenter label="Capability">
      <BadgeContainer>
        <CapabilityBadge capability="Contextual Signal" />
      </BadgeContainer>
    </BadgeRowCenter>

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

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

        <ProductRequiredBadge product="Contextual" />
      </BadgeContainer>
    </BadgeRowCenter>
  </div>

  <p
    style={{
  margin: 0,
  fontSize: "0.875rem",
  color: "#6b7280",
  lineHeight: "1.5",
}}
  >
    IBM Watson delivers contextual targeting capabilities, allowing publishers
    to serve relevant ads based on on-page content without user identifiers.
  </p>
</Card>

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

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

## Overview

IBM Watson Natural Language Understanding (NLU) analyzes page content and classifies it into standardized categories. Our integration enriches your `Pageview` events with contextual labels aligned to the IAB taxonomy, with optional advanced NLU signals (e.g. concepts, entities, sentiment) where enabled. This makes it possible to build and activate privacy-safe contextual strategies without user identifiers.

This integration is a Source:

* **Source:** Permutive enriches `Pageview` events with contextual classifications from IBM Watson.

Use cases include:

* Build contextual cohorts using IAB taxonomy labels (e.g. Sports, News/Politics).
* Apply brand suitability and safety rules by including/excluding categories.
* Power cookie-less targeting by using contextual cohorts across your inventory.
* (Advanced) Use entities, concepts and sentiment for niche, high-intent targeting.
* (Advanced) Standardize contextual labels that can be mapped into downstream activations.

## Environment Compatibility

| Environment    | Supported    | Notes |
| -------------- | ------------ | ----- |
| **Web**        | <YesBadge /> | --    |
| **iOS**        | <YesBadge /> | --    |
| **Android**    | <YesBadge /> | --    |
| **CTV**        | <NoBadge />  | --    |
| **API Direct** | <NoBadge />  | --    |

## Prerequisites

* **Permutive SDK**: Deployed on your web, iOS, or Android properties where you want content classified.
* **Permutive enablement**: IBM Watson must be enabled for your workspace by Permutive (quotas and thresholds are configured during enablement).
* **Accessible content**: Content should be accessible to classifiers. For paywalled or bot-protected pages, configure an allow mechanism (see Setup) so classifiers can fetch full content.
* **Classification quota**: Ensure your monthly classification quota covers expected volume.

<Expandable title="Advanced: Paywalls and bot checks">
  Some sites block non-user traffic. If classifiers cannot fetch content, you
  can configure a URL parameter in **Contextual > Catalog > Settings** that will be appended to classification requests. Configure your paywall to allow bypass when this parameter is present. The standard parameter is `bot-access=true`, though custom parameter names and values can be configured. Alternatively, allowlist traffic based on the Autonomous System Number (ASN) and User-Agent header of Watson requests.
</Expandable>

## Setup

<Steps>
  <Step title="Enable IBM Watson">
    Contact your Customer Success Manager (CSM) to enable IBM Watson for your workspace.
  </Step>

  <Step title="Configure classification settings">
    In the Permutive dashboard, navigate to **Contextual > Catalog** and locate IBM Watson. Configure your settings including:

    * **Requested Types**: Specify which classification types to request (Categories, Concepts, Emotion, Entities, Keywords, Sentiment)
    * **Domains**: Restrict classifications to specific domains to optimize quota usage. The domains shown are based on what you have defined under **Settings > Domains & App names**
    * **Quota**: Maximum monthly classification quota, managed by Permutive. Once the quota is reached, no more content will be classified until the next month
    * **Selective Classifications Threshold**: Set a minimum traffic threshold to classify only high-traffic URLs, optimizing quota usage. The default threshold is **20 pageviews within 24 hours** before initial classification is triggered
    * **XPath** (IBM Watson specific): Improve classifications by specifying a selector for the article body. This ensures other content like featured articles doesn't influence classifications. If the XPath does not return any results for a URL, a second classification request is issued without the XPath selector
  </Step>

  <Step title="(Optional) Configure access for paywalled content">
    If your site uses a paywall or bot mitigation that blocks classifier requests, configure an allow mechanism. Navigate to **Contextual > Catalog > Settings** and configure a URL parameter (e.g., `bot-access=true`) that will be appended to classification requests. Configure your paywall to allow bypass when this parameter is present. Alternatively, your DevOps team can allowlist traffic based on the Autonomous System Number (ASN) and User-Agent header of Watson requests.
  </Step>

  <Step title="Verify enrichment">
    After enablement, browse several article pages and check in your Permutive dashboard that `Pageview` events contain Watson classifications. You can preview classifications by hovering over the IBM Watson tile in the Catalog and clicking "Preview". Remember that pages must meet the configured threshold before they are classified.
  </Step>
</Steps>

## Data Types

With IBM Watson enabled, Permutive enriches your `Pageview` events with contextual data. Permutive automatically updates your event schema to include these properties. The exact schema enabled for your workspace may vary.

<AccordionGroup>
  <Accordion title="Pageview (standard)">
    Standard enrichment aligned to the IAB taxonomy.

    <ResponseField name="contextual.classifications.categories" type="list[object]">
      List of category classifications detected for the page. Each object contains:

      * `provider` (string, required): "watson"
      * `value` (string, required): The classification category ID (e.g., "201"). The dashboard uses the taxonomy to display human-readable names
      * `taxonomy` (string, required): "iab\_2\_0"
      * `confidence` (float, required): Confidence score for the classification (e.g., 0.72)
      * `reason` (string, optional): Explanation for why this classification was made
    </ResponseField>
  </Accordion>

  <Accordion title="Pageview (advanced NLU)">
    Additional enrichment fields may be enabled for advanced use cases.

    <ResponseField name="contextual.classifications.concepts" type="list[object]">
      High-level concepts detected in the content. Each object contains:

      * `provider` (string, required): "watson"
      * `value` (string, required): The concept name (e.g., "Social network service")
      * `confidence` (float, required): Confidence score from 0 to 1 (e.g., 0.41)
    </ResponseField>

    <ResponseField name="contextual.classifications.entities" type="list[object]">
      Named entities detected in the content. Each object contains:

      * `provider` (string, required): "watson"
      * `value` (string, required): The entity name (e.g., "Thomas J. Watson")
      * `confidence` (float, required): Confidence score from 0 to 1
    </ResponseField>

    <ResponseField name="contextual.classifications.keywords" type="list[object]">
      Important keywords detected. Each object contains:

      * `provider` (string, required): "watson"
      * `value` (string, required): The keyword phrase (e.g., "curated online courses")
      * `confidence` (float, required): Confidence score from 0 to 1
    </ResponseField>

    <ResponseField name="contextual.classifications.sentiments" type="list[object]">
      Sentiment analysis for the content. Each object contains:

      * `provider` (string, required): "watson"
      * `value` (string, required): The sentiment label (e.g., "positive", "neutral", "negative")
      * `confidence` (float, required): Confidence score from 0 to 1
    </ResponseField>
  </Accordion>
</AccordionGroup>

## Troubleshooting

<AccordionGroup>
  <Accordion title="Page not classified (no labels present)">
    Confirm the URL has met the minimum traffic threshold for classification.
    The default threshold is **20 pageviews within 24 hours**. Low-traffic or newly published pages may classify later. Contact Permutive Support to check if a specific URL has been classified or to verify your threshold configuration.
  </Accordion>

  <Accordion title="Monthly classification quota reached">
    If your monthly quota is reached, new URLs will not be classified until the next
    month. Contact your Customer Success Manager to review quotas.
  </Accordion>

  <Accordion title="Paywall or bot protection blocking classification">
    Classifier requests must be able to fetch the full article HTML. Configure your paywall to allow bypass using a URL parameter (e.g., `bot-access=true`). Set this in the Permutive dashboard under **Contextual > Catalog > Settings**, then configure your paywall system to allow access when this parameter is present in the URL. Alternatively, your DevOps team can allowlist Watson traffic based on the Autonomous System Number (ASN) and the User-Agent header.
  </Accordion>

  <Accordion title="Inaccurate or unexpected category assignment">
    Check that the page has sufficient on-page text and a correct canonical URL.
    Where needed, review advanced NLU signals or retest after content updates.
  </Accordion>
</AccordionGroup>

## Changelog

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