---
layout: page_v2
page_type: module
title: Module - Viewability
description: Generic Viewability module, tracks element viewability based on given criteria
module_code: viewability
display_name: Viewability
enable_download: false
sidebarType: 1
---

# Generic Viewability

{:.no_toc}

- TOC
{:toc}

## Overview

{: .alert.alert-danger :}
Disclaimer: A potential security risk has been identified in this module. We do not recommend its usage unless you're confident about
the source of all code running on the page.

This module will trigger a viewability pixel when a given HTML element becomes viewable according to custom viewability criteria.

Features:

- Does not depend on publishers using GAM ad server (i.e. does not use GPT's ImpressionViewableEvent).
- Enables custom viewability criteria (timeInView and inViewThreshold).
- Aims to provide (and in some ways extend) functionality of <https://github.com/InteractiveAdvertisingBureau/openvv-html> , but keeping the size to the bare minimun (openvv-html is ~26kb in size).
- Enables publishers to track viewability through callbacks or img/js pixels.
- Supports all mediatypes.
- Enables buy side to track viewability by posting a message from within the creative iframe (including the postMessage call in the ad markup), thus avoiding custom viewability scripts.

{: .alert.alert-warning :}
This module does not work on IE because it uses the IntersectionObserver.

Note that there are other viewability modules in Prebid.js:

- [Bid Viewability - Ad Server Independent](/dev-docs/modules/bidViewableIO.html)
- [Bid Viewability - GAM](/dev-docs/modules/bidViewable.html)
- [Browsi Viewability](/dev-docs/modules/browsiRtdProvider.html)

## Usage

The viewability module provides two functions: `startMeasurement` and `stopMeasurement` which can be used to enable viewability measurements.
These functions are intended to be added to the page. Here's how they work:

1. startMeasurement creates a browser [IntersectionObserver](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API) which triggers when the defined div is in view according to the defined criteria.
2. When the criteria is met, the IntersectionObserver is cancelled and the supplied tracking URL is hit (as an image or iframe) or the supplied callback function is called.
3. If for any reason the viewability measurement should be stopped (e.g. a slide show changed the contents), the stopMeasurement function can be used.

### startMeasurement

This function has 4 positional parameters when called as a function: `pbjs.viewability.startMeasurement(vid, element, tracker, criteria)`:

{: .table .table-bordered .table-striped }
| pos | param | scope | type | description | example |
|-----|-------|-------|------|-------------|---------|
| 1 | vid | required | string | unique viewability identifier, used to reference particular tracker which can later be used to stop the measurement. It allows for multiple trackers, with different criteria to be registered for a given HTML element, independently. vid is not autogenerated by startMeasurement(), it needs to be provided by caller so that it doesn't have to be posted back to the source iframe (in case viewability is started from within the creative). | 'test-div-1' |
| 2 | element | required | reference | reference to the HTML element that needs to be tracked. | test-div |
| 3 | tracker | required | object | an object type with two properties, `method` ('img','js','callback') and `value` which can be an URL string for 'img' and 'js' trackers, or a function for 'callback' tracker. | `{ method: 'img', value: 'http://my.tracker/123' }` |
| 4 | criteria | required | object | an object type with two properties, `inViewThreshold` which is a number (0, 1.0] representing a percentage of viewable element we're aiming at, and `timeInView` which is a number of milliseconds that a given element needs to be in view continuously, above a threshold. | `{ inViewThreshold: 0.5, timeInView: 1000 }` |

When a tracker needs to be started without direct access to Prebid.js, postMessage mechanism can be used to invoke `startMeasurement` with the following payload:

{: .table .table-bordered .table-striped }
| param | scope | type | description | example |
|-------|-------|------|-------------|---------|
| vid | required | string | unique viewability identifier. See the description above. | 'test-div-1' |
| tracker | required | object | see above | `{ method: 'img', value: 'http://my.tracker/123' }` |
| criteria | required | object | see above | `{ inViewThreshold: 0.5, timeInView: 1000 }` |
| message | required | string | must be 'Prebid Viewability' | 'Prebid Viewability' |
| action | required | string | must be 'startMeasurement' | 'startMeasurement' |
| elementId | optional | string | element ID. The message listener can figure this out from the source iframe. | 'test-div' |

### stopMeasurement

This function has only 1 parementer when called as a function: `pbjs.viewability.stopMeasurement()`:

{: .table .table-bordered .table-striped }
| pos |  param | scope | type | description | example |
|-----|-------|-------|------|-------------|---------|
| 1 | vid | required | string | the unique viewability identifier, referencing an already started viewability tracker. | 'test-div-1' |

When a tracker needs to be stopped without direct access to Prebid.js, postMessage mechanism can be used here as well to invoke `stopMeasurement`, providing payload with these fields:

{: .table .table-bordered .table-striped }
| param | scope | type | description | example |
|-------|-------|------|-------------|---------|
| vid | required | string | unique viewability identifier. See the description above. | 'test-div-1' |
| message | required | string | must be 'Prebid Viewability' | 'Prebid Viewability' |
| action | required | string | must be 'stopMeasurement' | 'stopMeasurement' |

## Examples

### Starting a viewability measurement when you have direct access to Prebid.js

```javascript
pbjs.viewability.startMeasurement(
    'test-div-1', 
    document.getElementById('test-div'),
    { method: 'img', value: 'http://my.tracker/123' },
    { inViewThreshold: 0.5, timeInView: 1000 }
);
```

### Starting a viewability measurement from within a rendered creative

```javascript
let viewabilityRecord = {
    vid: 'ae0f9',
    tracker: { method: 'img', value: 'http://my.tracker/123'},
    criteria: { inViewThreshold: 0.5, timeInView: 1000 },
    message: 'Prebid Viewability',
    action: 'startMeasurement'
}

window.parent.postMessage(JSON.stringify(viewabilityRecord), '*');
```

### Stopping the viewability measurement when you have direct access to Prebid.js

```javascript
pbjs.viewability.stopMeasurement('test-div-1');
```

### Stopping the viewability measurement from within a rendered creative

```javascript
let viewabilityRecord = {
    vid: 'ae0f9',
    message: 'Prebid Viewability',
    action: 'stopMeasurement'
}
window.parent.postMessage(JSON.stringify(viewabilityRecord), '*');
```

## Related Reading

- Alternate module: [Bid Viewability - Ad Server Independent](/dev-docs/modules/bidViewableIO.html)
