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

# Equativ

> Integrate with Equativ for ad server and SSP functionality.

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/tY6HQAw8J0a8II15/images/integrations/logos/equativ-icon.png?fit=max&auto=format&n=tY6HQAw8J0a8II15&q=85&s=d2e30a2fa256d9c1eaa9ce0040a28d92" alt="Equativ" style={{ maxWidth: '32px', maxHeight: '32px', display: 'block' }} width="32" height="32" data-path="images/integrations/logos/equativ-icon.png" />
    </div>

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

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

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

    <BadgeRowCenter label="Capability">
      <BadgeContainer>
        <CapabilityBadge capability="Event Collection" />

        <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' }}>
    Equativ (formerly Smart AdServer) provides publishers with an independent ad server and SSP for managing and monetizing inventory.
  </p>
</Card>

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

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

## Overview

Equativ (formerly Smart AdServer) is an independent advertising technology platform providing publishers with ad server and SSP functionality for managing and monetizing their digital inventory. Our integration with Equativ enables real-time cohort activation and impression event collection.

This integration is Bidirectional:

* **Source:** Permutive collects impression events from Equativ ad server, enabling cohort creation based on campaign delivery data.
* **Destination:** Permutive cohorts are activated in Equativ as keyword targeting options, with cohort IDs stored in local storage and passed as key-value pairs in ad requests to Equativ.

Use cases include:

* Activate Permutive cohorts in Equativ for real-time audience targeting across display and video inventory.
* Collect impression data from Equativ campaigns to build cohorts based on ad exposure and campaign performance.
* Target campaigns using first-party data segments from Permutive.
* Enable publishers to monetize inventory more effectively with data-driven targeting.
* Leverage Equativ's keyword targeting capabilities with Permutive cohorts for flexible campaign configuration.

## Environment Compatibility

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

## Prerequisites

* **Equativ Network ID**: Your unique Equativ network identifier. See [How to find the Network ID](https://help.smartadserver.com/s/question/0D51v00005cG9vXCAS/how-can-i-get-my-network-id) in Equativ's documentation.
* **Equativ Username and Password**: API credentials with permissions to create and manage keyword targeting in your Equativ account.
* **Permutive SDK**: The Permutive SDK must be deployed on your web pages where Equativ ad requests are made.
* **Access to Equativ Campaign Setup**: Ability to configure keyword targeting in your Equativ campaigns and insert creative scripts for impression tracking.

## Setup

<Tabs>
  <Tab title="Primary Setup Steps">
    <Steps>
      <Step title="Configure Integration in Permutive Dashboard">
        Navigate to the integrations page in the Permutive dashboard (Settings → Integrations) and add the Equativ integration.

        1. Click the **Add Integration** button
        2. Select **Equativ** from the list of available integrations
        3. Enter your Equativ credentials:
           * **Network ID**: Your Equativ network identifier
           * **Username**: Your Equativ API username
           * **Password**: Your Equativ API password
        4. Click **Save**

        Once configured, Permutive will automatically create a keyword group in your Equativ account and push activated cohort names as keywords for targeting.
      </Step>

      <Step title="Verify Setup">
        After configuring the integration, verify that:

        1. The integration appears as active in your Permutive dashboard integrations page
        2. A Permutive keyword group has been created in your Equativ account
        3. You can see activated cohorts appearing as keywords in the Equativ targeting interface
      </Step>

      <Step title="Optional: Set up Impression Tracking">
        If you want to collect impression events from Equativ campaigns for cohort building and analytics, discuss this with your Customer Success Manager first.

        This requires:

        * A new event schema to be set up within Permutive
        * Additional Web code implementation (documented in the Web tab below)

        Once the event schema is configured, you can proceed with implementing the impression tracking code.
      </Step>
    </Steps>
  </Tab>

  <Tab title="Web">
    ## Cohort Activation on Web

    To pass Permutive cohorts in your Equativ ad requests, include the cohort data from local storage in the request's `target` parameter:

    ```javascript theme={"dark"}
    <!-- Equativ Smart Setup -->
    <script type="application/javascript" src="https://ced.sascdn.com/tag/[NETWORK_ID]/smart.js" async></script>

    <script type="application/javascript">
      var sas = sas || {}
      sas.cmd = sas.cmd || []

      sas.cmd.push(function () {
        sas.setup({
          networkid: [NETWORK_ID],
          domain: 'https://www.smartadserver.com',
          async: true,
          renderMode: 0
        })
      })

      // Retrieve Permutive cohorts from local storage
      var permutive_cohorts_for_smart = JSON.parse(window.localStorage.getItem('_psmart')) || []

      sas.cmd.push(function () {
        sas.call('std', {
          siteId: [SITE_ID],
          pageId: [PAGE_ID],
          formatId: [FORMAT_ID],
          target: `permutive=${permutive_cohorts_for_smart.join(',')}`
        })
      })
    </script>

    <!-- Render ad format -->
    <div id="sas_[FORMAT_ID]"></div>
    <script type="application/javascript">
      sas.cmd.push(function () {
        sas.render('[FORMAT_ID]')
      })
    </script>
    ```

    **Important Notes:**

    * Replace `[NETWORK_ID]`, `[SITE_ID]`, `[PAGE_ID]`, and `[FORMAT_ID]` with your actual Equativ configuration values
    * The Permutive SDK automatically populates the `_psmart` local storage field with activated cohort IDs
    * See the [Equativ Tagging Guide](https://help.smartadserver.com/s/article/Tagging-guide) for details on extracting your configuration values

    ## Advanced: Enable Impression Event Collection

    To collect impression events from Equativ for cohort building and analytics:

    1. **Add Creative Script**: In your Equativ ad server, add the following script to the **Creative Section** of campaigns you want to track:

    ```javascript theme={"dark"}
    <script>
    ;(function () {
    var data = {
      advertiserId: "[sas_advertiserId]" || "[sas_rtb_advertiserId]" || null,
      campaignId: "[sas_campaignId]" || "[sas_rtb_campaignId]" || null,
      creativeId: "[sas_creativeId]" || "[sas_rtb_creativeId]" || null,
      insertionId: "[sas_insertionId]" || null,
      dealId: "[sas_rtb_dealId]" || null,
      cpm: "[sas_cpm]" || "[sas_rtb_clearedPricePublisherCurrency]" || null,
      tagId: "[sas_tagId]" ||  null,
      creativeHeight: "[sas_creativeHeight]" || null,
      creativeWidth: "[sas_creativeWidth]" || null,
      keywords: "[sas_keywordTargeting]" || null
    }
    window.parent.postMessage({
      origin: 'permutive',
      type: 'smart-ad-impression',
      arguments: data
    }, "*")
    })()
    </script>
    ```

    This script uses Equativ macros to capture impression metadata and send it to Permutive via postMessage.

    2. **Add Event Queue Script** (Optional but Recommended): To handle impressions that fire before the Permutive SDK has fully initialized, add this script alongside your Permutive deployment tag:

    ```javascript theme={"dark"}
    ;(function () {
    var messageDataQueue = []
    var sdkReady = false
    var listener = function (event) {
      if (typeof event.data === 'object' && 'origin' in event.data && event.data.origin === 'permutive') {
        if (event.data.type === 'sdk-init') {
          sdkReady = true
          window.removeEventListener('message', listener)
          messageDataQueue.forEach(function (msgData) {
            window.postMessage(msgData, '*')
          })
          return
        }
      }
      if (!sdkReady) {
        messageDataQueue.push(event.data)
      }
    }
    window.addEventListener('message', listener, false)
    })()
    ```

    This ensures all impression events are captured and processed, even those that occur during page load.
  </Tab>
</Tabs>

## Data Types

With your Equativ integration setup, you'll see the following additional event types collected in Permutive:

<AccordionGroup>
  <Accordion title="Equativ Impression">
    Fired when an ad impression is served through Equativ ad server. This event captures campaign, creative, and targeting metadata for cohort building and analytics.

    <ResponseField name="advertiserId" type="string">
      The ID of the advertiser associated with the impression. May come from direct campaigns (`sas_advertiserId`) or programmatic campaigns (`sas_rtb_advertiserId`).
    </ResponseField>

    <ResponseField name="campaignId" type="string">
      The ID of the campaign associated with the impression. May come from direct campaigns (`sas_campaignId`) or programmatic campaigns (`sas_rtb_campaignId`).
    </ResponseField>

    <ResponseField name="creativeId" type="string">
      The ID of the creative that was displayed. May come from direct campaigns (`sas_creativeId`) or programmatic campaigns (`sas_rtb_creativeId`).
    </ResponseField>

    <ResponseField name="insertionId" type="string">
      The ID of the insertion order (equivalent to line item ID in other ad servers). Used for campaign reporting and analysis.
    </ResponseField>

    <ResponseField name="dealId" type="string">
      The deal ID for programmatic transactions (`sas_rtb_dealId`). Available only for programmatic impressions.
    </ResponseField>

    <ResponseField name="cpm" type="string">
      The CPM value for the impression. May be the standard CPM (`sas_cpm`) or the cleared price in publisher currency (`sas_rtb_clearedPricePublisherCurrency`) for programmatic impressions.
    </ResponseField>

    <ResponseField name="tagId" type="string">
      The Equativ tag ID associated with the ad placement.
    </ResponseField>

    <ResponseField name="creativeHeight" type="string">
      The height of the creative in pixels.
    </ResponseField>

    <ResponseField name="creativeWidth" type="string">
      The width of the creative in pixels.
    </ResponseField>

    <ResponseField name="keywords" type="string">
      The keyword targeting parameters applied to the impression, including Permutive cohort IDs if cohort activation is enabled.
    </ResponseField>
  </Accordion>
</AccordionGroup>

<Note>
  Impression events require additional setup in the Equativ Creative Section. See the "Advanced: Enable Impression Event Collection" section in Setup for implementation details.
</Note>

## Troubleshooting

<AccordionGroup>
  <Accordion title="Cohorts not appearing in Equativ keyword targeting">
    **Symptoms:** Activated cohorts don't appear as available keywords in Equativ campaign targeting interface.

    **Solutions:**

    * Verify the Equativ integration is properly configured in the Permutive dashboard with correct Network ID, Username, and Password
    * Check that cohorts have been activated for Equativ in the Permutive dashboard (either via cohort settings or cohort activations page)
    * Confirm that a Permutive keyword group has been created in your Equativ account (this should happen automatically upon integration setup)
    * Allow a few minutes for newly activated cohorts to sync to Equativ - keyword creation is not instantaneous
    * Verify your Equativ API credentials have permissions to create and manage keyword targeting
  </Accordion>

  <Accordion title="Cohorts not being passed in ad requests">
    **Symptoms:** Permutive cohorts are not included in the `target` parameter of Equativ ad requests, or targeting doesn't work as expected.

    **Solutions:**

    * Verify the `_psmart` local storage field is being populated by the Permutive SDK - check browser developer tools → Application → Local Storage
    * Ensure your Equativ ad request code is correctly reading from `localStorage.getItem('_psmart')` and parsing the JSON
    * Confirm the `target` parameter in your `sas.call()` includes the Permutive cohorts: `target: 'permutive=' + permutive_cohorts_for_smart.join(',')`
    * Check that the Permutive SDK loads before the Equativ ad request is made
    * Verify the cohorts are activated with an Equativ activation (not just other activations)
  </Accordion>

  <Accordion title="Impression events not being collected">
    **Symptoms:** Equativ impression events are not appearing in Permutive analytics or event stream.

    **Solutions:**

    * Verify the impression tracking script has been added to the Creative Section in Equativ ad server
    * Check that the `permutiveEventSmart` postMessage is being sent - use browser developer tools → Console to check for errors
    * Ensure the Permutive SDK is loaded on pages where Equativ ads are served
    * If using the optional event queue script, verify it's placed alongside the Permutive deployment tag (not inside the creative)
    * Check browser console for any cross-origin or security errors that might block postMessage communication
    * Confirm the creative script is using the correct Equativ macros (e.g., `[sas_advertiserId]`, `[sas_campaignId]`)
  </Accordion>

  <Accordion title="Equativ keyword targeting uses OR logic instead of AND">
    **Symptoms:** When targeting multiple Permutive cohorts, Equativ treats them as OR conditions rather than AND conditions.

    **Solutions:**

    * This is expected behavior - Equativ's keyword targeting uses OR logic by default when multiple keywords are selected from the same keyword group
    * To create AND logic or more complex targeting combinations, you must manually enter cohort IDs in the Equativ targeting interface rather than selecting them from the dropdown
    * See [Equativ's keyword targeting documentation](https://help.smartadserver.com/s/article/Using-keyword-targeting) for details on advanced targeting syntax
    * Consider building more specific cohorts in Permutive that combine your desired conditions, then activate those single cohorts to Equativ
  </Accordion>

  <Accordion title="Unable to add Equativ integration in dashboard">
    **Symptoms:** Error when trying to add or configure the Equativ integration in the Permutive dashboard.

    **Solutions:**

    * Verify you have the correct Equativ Network ID - see [How to find the Network ID](https://help.smartadserver.com/s/question/0D51v00005cG9vXCAS/how-can-i-get-my-network-id)
    * Confirm your Equativ API credentials are correct and have not expired
    * Check that your Equativ user account has API access and permissions to create keyword groups
    * If the issue persists, contact Permutive support with the error message
  </Accordion>
</AccordionGroup>

## Changelog

### January 2022

* Added support for Equativ impression event collection via creative pixel
* Enabled Equativ Campaign Insights dashboards for customers with integration configured

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