DTVR Domless SDK

From Engineering Client Portal

Revision as of 18:46, 31 July 2024 by AmySockanathan (talk | contribs) (DOMless SDK DTVR)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

License

Nielsen SDK contains material that is protected by copyright laws, patent laws, trade secret laws, and by international treaty provisions and is Copyright © 2024 The Nielsen Company (US) LLC. All intellectual property rights and licenses therein are reserved by The Nielsen Company (US) LLC and its licensors. Please read the license agreement presented here, which must be accepted in order to download the Nielsen SDKs. For more information, reach out to your Nielsen Technical Account Manager(TAM).

DOM-less SDK DTVR Video Introduction

The Nielsen DOM-less SDK is a Javascript based cross-platform library that clients can use to integrate the Nielsen Digital Content Rating or Digital TV Rating measurement in ReactNative or NodeJS apps.

The Digital TV Ratings (DTVR) product provides content consumption measurement on client mobile apps or webpages. This measurement includes insight into the total time a user spent watching the tracked content, video player events, and much more. This example provides the steps to implement the DTVR Video product in a sample NodeJS app. It includes:

  • DOM-less SDK Initialization
  • DTVR Metadata: information about the content being tracked
  • DTVR Events/API calls

By the end of this guide you will have the needed steps to integrate Nielsen's DOM-less SDK in your app.

DOM-less SDK DTVR Video Step 1 - Obtain AppID

To begin using the DOM-less SDK you will need to obtain an Application ID (AppId)

Item Description Source
App ID (appid) Unique ID assigned to the player/site and configured by product Contact your Nielsen TAM

The appid is a 37 character unique ID assigned to the player/site and configured by product and is required when creating a new instance of the DOM-less SDK on the app.

Example: PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXX

DOM-less SDK DTVR Video Step 2 - SDK Initialization

This project is an API that allows clients to integrate the Nielsen SDK in DOM-less environments like React Native, NodeJS, etc.

Refer to the " DOM-less SDK initialization " section in the DOM-less SDK API Reference Guide.

SDK Initialization

The following table contains the list of arguments that can be passed

Parameter / Argument Description Source Required? Example
appid Unique Nielsen ID for the application. The ID is a GUID data type. If you did not receive your App ID, let us know and we will provide you. Nielsen-specified Yes PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
instanceName DOM-less SDK instance name Client provided Yes String eg. abcdefg
appName Application name Client provided Yes appName: 'BSDK RN Sample App'
deviceId Device ID Client provided Yes deviceId: '38400000-8cf0-11bd-b23e-10b96e40000d'
nol_sdkDebug Enables Nielsen console logging. Only required for testing Client-provided No nol_sdkDebug: 'debug'
domlessEnv Specify the domless environment.

"1" for ReactNative "2" for Amazon "3" for NodeJS "4" for Custom

Client-provided Yes domlessEnv: '1'

DOM-less SDK DTVR Video Step 3 - Create DTVR Metadata Object

Events that can be passed to `ggPM` method

1. loadMetadata - This event is used to send DTVR metadata to the Nielsen SDK. This event should be called when the video metadata is loaded.

    instance.ggPM('loadMetadata', {
        'type': 'content',
        'adModel': '1'
    });

2. sendID3 - This event is used to send the id3 event to the Nielsen SDK. This event should be called when the id3 event is triggered, passing the id3 data from the stream.

    instance.ggPM('sendID3', '<id3 metadata received>');

3. end - This event is used to send the end event to the Nielsen SDK. This event should be called when the video playback is finished, passing the playhead at that time.

    instance.ggPM('end', 300);
Events that can be passed to and processed by processEvent method

1. `blur` - This event should be passed to processEvent when the app goes to the background.

    instance.processEvent({'type': 'blur', 'timestamp': Date.now()});

2. `focus` - This event should be passed to processEvent when the app goes to the foreground.

    instance.processEvent({'type': 'focus', 'timestamp': Date.now()});

3. `appclose` - This event should be passed prior to closing the app.

    instance.processEvent({'type': 'appclose', 'timestamp': Date.now()});
ID3 Tags

ID3_Payload is the container to pass the retrieved ID3 tag from the stream. The player should look for 'PRIV' ID3 tags and send 'owner' field (which typically starts from "www.nielsen.com") through this API. Refer to DTVR Event Listeners section below for more information.

Sample ID3 Tags

www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/X100zdCIGeIlgZnkYj6UvQ==/AAAB2Jz2_k74GXSzx4npHuI_JwJd3QSUpW30rDkGTcbHEzIMWleCzM-uvNOP9fzJcQMWQLJqzXMCAxParOb5sGijSV9dNM3QiBniJYGZ5GI-lL1fXTTN0IgZ4iWBmeRiPpS9AAAAAAAAAAAAAAAAAAAAAFJWFM5SVhTONNU=/00000/00000/00

www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/R8WHe7pEBeqBhu8jTeXydg==/AAICoyitYqlxT7n6aZ0oMCGheFi4CXFp46AMUPZz1lMr_M9tr3_cjee1SHqxrOiVerMDLeyn9xzocZSKwi746Re8vNOtpNCAZjYABs_J0R25IHpvOc1HS8QHGgD5TgOJeS6gX100zdCIGeIlgZnkYj6UvVJWFNhSVhTiPE0=/00000/46016/00

DOM-less SDK DTVR Step 4 - Basic Set of Events - Sample Playback

Sample Nielsen BSDK-Domless NodeJS Example

Sample DTVR Video Integration

import { BsdkInstance } from 'bsdk-domless'; 
const nsdkConfig = { 
    app_id: 'PXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX',
    instance_name: 'videoInstance',
};
const implementationHooks = { 
    Log: {
        info: function (log: string) {
                console.info(log);
            },
        debug: function (log: string) {
                console.debug(log);
            },
        warn: function (log: string) {
                console.warn(log);
            },
        error: function (error: string) {
                console.error(error);
            }
        },
    Storage: {
        setItem: async function (key: any, value: string) {
            /** 
            * Sets a string value for given key. This operation can either modify an existing entry,
            * if it did exist for given key, or add new one otherwise. 
            * In order to store object value, you need to serialize it, e.g. using JSON.stringify().
            */
        },
        getItem: async function (key: any) {
            /**
            * Gets a string value for given key. This function can either return a string value for
            * existing key or return null otherwise. 
            * In order to store object value, you need to deserialize it, e.g. using JSON.parse().
            */ 
        },
        removeItem: async function (key: any) {
            /**
            * Removes item for a key, invokes (optional) callback once completed. 
            */
        }
    },
    Fetch: async function (url: string | URL | Request, options: any) {
        /** 
        * We require that client pass in User-Agent header via options in Fetch request
        */
        const clientOpts = { 
            headers: {
                "User-Agent": "react-native-domless/1.6.7.42 Dalvik/2.1.0 (Linux; U; Android 5.1.1; Android SDK built for x86 Build/LMY48X)"
            }
        }
        const data = Object.assign(options, clientOpts);
        const response = await fetch(url, data);
        if (response.ok) {
            return response;
        } else {
            throw new Error('Request failed');
        }
    },
    SetTimeout: function (callback: () => void, timeout: number | undefined) {
        return setTimeout(callback, timeout);
    },
    SetInterval: function (callback: () => void, interval: number | undefined) {
        return setInterval(callback, interval);
    },
    ClearTimeout: function (timeout: string | number | NodeJS.Timeout | undefined) {
        return clearTimeout(timeout); 
    },
    ClearInterval: function (interval: string | number | NodeJS.Timeout | undefined) {
        return clearInterval(interval);
    }
};
const nSdkInstance = new BsdkInstance(
    nsdkConfig.app_id,
    nsdkConfig.instance_name,
    {
        appName: 'BSDK RN Sample App',
        deviceId: 'testDeviceId',
        nol_sdkDebug: 'debug', // remove debug flag when going to production domlessEnv:
        // "1" for React Native | "2" for Amazon | "3" for NodeJS | "4" for Custom
        // reference SDK interface documentation
        // for additonal metadata properties
    },
    implementationHooks
); 
// Sample VideoPlayer component
const VideoPlayer = (props) => {
    /**
    * Implementation of video player component will vary across the board, for Nielsen DOM-less SDK integration
    * clients need only setup event listeners with corresponding ggPM() calls. 
    * Please refer to chosen video player documentation on available events
    */
    const video = useRef<Video>(null);
    let previousPlayhead = 0; // keep track of previous playhead position
    let metadataLoaded = false; // in case of replay scenario set flag for metadata load 
    // Sample video metadata 
    const videometadata = {
        'type': 'content',
        'adModel': '1'
    }
    const setUpEventListeners = (): void => {
        video.addEventListener('ended', onEnded);
        video.addEventListener('playing', onPlay);
        video.addEventListener('metadata', onMetadata )
    };

    const onEnded = () => {
        // Nielsen SDK ggPM 'end' event
        if (nSdkInstance) {
        nSdkInstance.then((instance: any) => {
            instance.ggPM('end', Math.round(video.currentTime));
            metadataLoaded = false;
        });
        }
    };

    // NOTE: some players may have an event when video metadata is loaded, recommended to use if available. E.g. loadedmetadata
    const onPlay = () => {
        // Nielsen SDK ggPM 'loadMetadata' event
        if (nSdkInstance && !metadataLoaded) {
            nSdkInstance.then((instance: any) => {
                instance.ggPM('loadMetadata', videometadata);
                metadataLoaded = true;
            });
        }
    };

    // NOTE: retireval of ID3 tags will vary by player and is primarily used for DTVR measurement
    const onMetadata = (data) = {
        if (data.metadata && data.metadata.key === 'PRIV') {
            nSdkInstance.then(instance => {
            instance.ggPM('sendID3', data.metadata.info);
            });
        }
    };

    return (
        <View>
            <Video
                source={{ uri: 'https://www.w3schools.com/html/mov_bbb.mp4' }}
            />
        </View>
    );
};