<file_sep>import { Placement } from './Placement';
import { User } from './User';

/**
 * To create a Request for ads, use {@link Request.Builder} to build the ad request.
 * <p>
 * Every Request must contain one or more Placements. Each placement represents a "slot" in which an ad may be served.
 * By specifying multiple placements, you can request multiple ads in a single call.
 * <p>
 * @see com.adzerk.android.sdk.AdzerkSdk
 */
export interface AdRequest {

    // list of placements where an ad can be served (required)
    placements: Placement[];

    // target to the user key used to identify a unique user
    user?: User;

    // zero or more keywords to use when selecting the ad
    keywords?: string[];

    // URL to use as the referrer when selecting an ad
    referrer?: string;

    // URL to use as the current page URL when selecting an ad
    url?: string;

    // UNIX epoch timestamp to use when selecting an ad
    time?: number;

    // IP address to use when selecting the ad; if specified, overrides the IP the request is made from
    ip?: string;

    // zero or more numeric creative ids to disregard when selecting an ad
    blockedCreatives?: number[];

    // hash of flight ids to arrays of UNIX epoch timestamps representing times the user viewed an ad
    // in the specified flight (used for frequency capping)
    flightViewTimes?: any;
}
<file_sep>import { User } from './User';
import { Decision } from './Decision';

/**
 * The DecisionResponse to an ad {@link Request}.
 * <p>
 * A DecisionResponse will contain zero or more {@link Decision}s, one per {@link Placement} that was sent in on the requestPlacement.
 * If no ad was selected for a given Placement, the corresponding Decision entry will be undefined (null).
 */
export interface DecisionResponse {
    // identifies the unique user that places the requestPlacement
    user: User;

    // each Decision represents the ad that was selected to be served for a given Placement
    decisions: Map<string, Decision>;
}
<file_sep>import { ContentData } from './ContentData';

const TYPE_HTML = 'html';
const TYPE_CSS = 'css';
const TYPE_JS = 'js';
const TYPE_JS_EXTERNAL = 'js-external';
const TYPE_RAW = 'raw';

const TEMPLATE_IMAGE = 'image';
const TEMPLATE_IMAGE_NO_WIDTH = 'image-nowidth';
const TEMPLATE_FLASH = 'flash';
const TEMPLATE_FLASH_NO_WIDTH = 'flash-nowidth';

/**
 * Each {@link Decision} contains one or more Contents. Combined, the Contents represent the creative that should
 * be displayed.
 * <p>
 * For example, a creative may contain a CSS stylesheet and a block of HTML. This would be represented as
 * two Contents, one with the type css and one with the type html.
 * <p>
 * Custom metadata set at the creative level will be passed in the Contents as the key customData.
 * <p>
 * If a content uses a predefined template, the template property will be set to the name of the template to use.
 * For example, an image content will have the {@link Content#TYPE_HTML} and the {@link Content#TEMPLATE_IMAGE}.
 * <p>
 *
 * @see Decision
 */
export interface Content {
    // the type of the content
    type: string;

    // name of the template used to render the content (unless TYPE_RAW)
    template: string;

    // the body of the custom template for TYPE_RAW content
    customTemplate: string;

    // rendered body of the content
    body: string;

    // contains a map of the creative data (title, height, width, etc.) and the creative metadata
    contentData: ContentData;
}
<file_sep>import { Content } from './content';
import { ContentData } from './ContentData';
import { AdzerkEvent } from './AdzerkEvent';

/**
 * A Decision represents the ad that was selected to be served for a given {@link Placement}.
 * <p>
 * A {@link DecisionResponse} will contain zero or more Decisions, one per Placement that was sent in on the requestPlacement.
 * If no ad was selected for a given Placement, the corresponding Decision entry will be undefined (null).
 */
export interface Decision {

    // id for the ad that was selected
    adId: number;

    // id for the creative in the selected ad
    creativeId: number;

    // id for the flight in the selected ad
    flightId: number;

    // id for the campaign in the selected ad
    campaignId: number;

    // url endpoint that, using a GET, triggers the recording of the click and redirects to the target
    clickUrl: string;

    // list of ad contents
    contents: Content[];

    // list if Events - the IDs and tracking URLs of custom events
    events: AdzerkEvent[];

    // url endpoint that, using a GET, triggers the recording of the impression
    impressionUrl: string;
}
<file_sep>// data key for the json metadata
const KEY_CUSTOM_DATA = 'customData';

// data key for image url
const KEY_IMAGE_URL = 'imageUrl';

// data key for title
const KEY_TITLE = 'title';

/**
 * Contains the data and metadata parsed from a Content element. Not intended for API consumers.
 * @see Content
 */
export interface ContentData {
    // map of creative data (title, height, width, etc) used to build the content body
    creativeData: Map<string, object>;

    // map of creative metadata; the deserialized JSON metadata from the creative
    creativeMetadata: Map<string, object>;

    // raw creative metadata JSON object; useful for clients needing custom deserialization
    creativeMetadataJson: any;
}
<file_sep>const ADVERTISERS = 'advertisers';
const CAMPAIGNS = 'campaigns';
const CREATIVES = 'creatives';
const FLIGHTS = 'flights';

/**
 * Contains the key to identify the User in a {@link DecisionResponse}
 * <p>
 * The response contains the key used to identify the unique user that places the request. All user keys
 * are generated by the API. You can target to a user when you place a {@link Request}.
 *
 * Not supported:
 * - pendingConversions, partnerUserIds, retargettingSegments, cookieMonster, dirtyCookies
 */
export interface User {
    key: string;
    isNew?: boolean;
    interests?: string[];
    customProperties?: any;
    optOut?: boolean;
    blockedItems?: Map<string, number[]>;
    flightViewTimes?: Map<number, number[]>;
    adViewTimes?: Map<number, number[]>;
    siteViewTimes?: Map<number, number[]>;
}
<file_sep>
/**
 * To make an ad {@link Request}, you will specify one of more Placements. Each Placement has a unique name to
 * identify a place where an can be served in your app. To request multiple ads in a single {@link Request} you
 * specify multiple Placements.
 * <p>
 * <pre>
 * {@code
 * // Build a Request with multiple Placements:
 * Request request = new Request.Builder()
 *     .addPlacement(new Placement(name1, networkId, siteId, adTypes))
 *     .addPlacement(new Placement(name2, networkId, siteId, adTypes))
 *     .build();
 * }
 * </pre>
 *
 *
 */
export interface Placement {
    // unique name for the placement (required)
    divName: string;

    // network id to use when selecting an ad (required)
    networkId: number;

    // site id to use when selecting an ad (required)
    siteId: number;

    // one or more integer ad types to use when selecting an ad (required)
    adTypes: number[];

    // zero or more zone ids to use when selecting an ad
    zoneIds?: number[];

    // campaign id; if specified, only consider ads in that campaign
    campaignId?: number;

    // flight id; if specified, only consider ads in that flight
    flightId?: number;

    // ad (flight-creative map) id; if specified, only serve that ad if possible
    adId?: number;

    // URL that should be used as the click-through target for the ad
    clickUrl?: string;

    // hash of key/value pairs used for custom targeting
    properties?: any;

    // array of numeric event types. Requests tracking URLs for custom events
    eventIds?: number[];
}
<file_sep>export { AdzerkService, AdzerkConfig, AdzerkConfigToken } from './adzerk.service';
<file_sep>const ID_VIEW_CONVERSION = 1;
const ID_CLICK_CONVERSION = 2;
const ID_SERVER_CONVERSION = 3;
const ID_UPVOTE = 10;
const ID_DOWNVOTE = 11;
const ID_DOWNVOTE_UNINTERESTING = 12;
const ID_DOWNVOTE_MISLEADING = 13;
const ID_DOWNVOTE_OFFENSIVE = 14;
const ID_DOWNVOTE_REPETITIVE = 15;
const ID_LIKE = 20;
const ID_SHARE = 21;
const ID_COMMENT = 22;
const ID_VISIBLE = 30;
const ID_HOVER = 31;
const ID_EXPAND = 32;
const ID_SHARE_FACEBOOK = 50;
const ID_SHARE_TWITTER = 51;
const ID_SHARE_PINTEREST = 52;
const ID_SHARE_REDDIT = 53;
const ID_SHARE_EMAIL = 54;
const ID_START = 70;
const ID_FIRST_QUARTILE = 71;
const ID_MIDPOINT = 72;
const ID_THIRD_QUARTILE = 73;
const ID_COMPLETE = 74;
const ID_MUTE = 75;
const ID_UNMUTE = 76;
const ID_PAUSE = 77;
const ID_REWIND = 78;
const ID_RESUME = 79;
const ID_FULLSCREEN = 80;
const ID_EXIT_FULLSCREEN = 81;
const ID_EXPAND_VIDEO = 82;
const ID_COLLAPSE = 83;
const ID_ACCEPT_INVITATION_LINEAR = 84;
const ID_CLOSE_LINEAR = 85;
const ID_SKIP = 86;
const ID_PROGRESS = 87;
const ID_COMMENT_REPLY = 101;
const ID_COMMENT_UPVOTE = 102;
const ID_COMMENT_DOWNVOTE = 103;
const ID_CUSTOM_01 = 104;
const ID_CUSTOM_02 = 105;
const ID_CUSTOM_03 = 106;
const ID_CUSTOM_04 = 107;
const ID_CUSTOM_05 = 108;
const ID_CUSTOM_06 = 109;
const ID_CUSTOM_07 = 110;

/**
 * Event information included in DecisionResponse to an ad requestPlacement. Once you call an Event URL, Adzerk will track that
 * event for the creative/campaign/advertiser etc. in Adzerk reporting.
 * <p/>
 * Events in Adzerk are data about a way a user interacts with an ad. Standard events included with all Adzerk
 * accounts are clicks, impressions, and conversions. Custom events are defined by the user of the account.
 */
export interface AdzerkEvent {
    /**
     *
     * @param id Event identifier
     * @param url Url to call to track an event
     */
    id: number;
    url: string;
}
<file_sep># adzerk-angular-sdk<file_sep>import { Injectable, Inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { InjectionToken } from '@angular/core';

import { AdRequest } from './rest/AdRequest';
import { DecisionResponse } from './rest/DecisionResponse';
import { User } from './rest/User';


export interface AdzerkConfig {
    apiKey: string;
    networkId: number;
    siteId: number;
    baseUrl?: string;
}

export const AdzerkConfigToken = new InjectionToken<AdzerkConfig>('adzerk-config');

/**
 * Service interface for Native Ads API
 */
@Injectable()
export class AdzerkService {
    private baseUrl: string;

    constructor(
        private http: HttpClient,
        @Inject(AdzerkConfigToken) private config: AdzerkConfig) {
        this.baseUrl = config.baseUrl || 'http://engine.adzerk.net';
    }

    /**
     * Request an Ad.
     * <p/>
     * NOTE: The placement in the Request corresponds to an ad placement on a page or app.
     */
    public async requestAds(request: AdRequest): Promise<DecisionResponse> {
        const options = {
            headers: {
                'Content-Type': 'application/json'
            },
            withCredentials: true
        };
        const res = await this.http.post(`${this.baseUrl}/api/v2`, request, options).toPromise();

        return <DecisionResponse>res;
    }

    /**
     * Set the custom properties of a User by specifying properties in a JSON string
     * <p/>
     * Example: POST http://engine.adzerk.net/udb/{networkId}/custom?userKey=<user-key>
     */
    public async setUserProperties(networkId: number, userKey: string, properties: any): Promise<any> {
        const options: any = {
            headers: {
                'Content-Type': 'application/json'
            },
            responseType: 'text',
            withCredentials: true
        };
        const res = await this.http.post(`${this.baseUrl}/udb/${networkId}/custom?userKey=${userKey}`,
            properties, options).toPromise();
        return res;
    }

    /**
     * Reads a User from UserDB.
     * <p/>
     * The User object contains the users key, custom properties, interests and additional details.
     * <p/>
     * Example:  GET http://engine.adzerk.net/udb/{networkid}/read?userKey=<user-key>
     */
    public async getUser(networkId: number, userKey: string): Promise<User> {
        const options = {
            headers: {
                'X-Adzerk-ApiKey': this.config.apiKey
            }
        };
        const res = await this.http.get(`${this.baseUrl}/udb/${networkId}/read?userKey=${userKey}`, options).toPromise();
        return <User>res;
    }

    /**
     * Sets a User interest. The User object has a list of behavioral interest keywords (ie, cars, sports, ponies).
     * <p/>
     * Example: GET http://engine.adzerk.net/udb/{networkId}/interest/i.gif?userKey=<user-key>&interest=<interest>
     */
    public async setUserInterest(networkId: number, userKey: string, interest: string): Promise<any> {
        const res = await this.http.get(`${this.baseUrl}/udb/${networkId}/interest/i.gif?userKey=${userKey}&interest=${interest}`
            , { responseType: 'arraybuffer' }).toPromise();
        console.log(`User interest '${interest}' set.`);
        return res;
    }

    /**
     * Sets a flag to allow User to opt-out of UserDB tracking. This call clears the entire user record and then
     * sets a value of "optedOut" to true.
     * <p/>
     * Example: GET http://engine.adzerk.net/udb/{networkid}/optout/i.gif?userKey=<user-key>
     */
    public async setUserOptout(networkId: number, userKey: string): Promise<any> {
        const options = {
            headers: {
                'X-Adzerk-ApiKey': this.config.apiKey
            }
        };
        return await this.http.get(`${this.baseUrl}/udb/${networkId}/optout/i.gif?userKey=${userKey}`, options).toPromise();
    }

    /**
     * Retargeting creates a new number set called Segments-{brandId} that contains each of the segments.
     * <p/>
     * Example: GET http://engine.adzerk.net/udb/{networkId}/rt/{brandId}/{segment}/i.gif?userKey=<user-key>
     */
    public async setUserRetargeting(networkId: number, brandId: number, segment: string, userKey: string): Promise<any> {
        const options = {
            headers: {
                'X-Adzerk-ApiKey': this.config.apiKey
            }
        };
        return await this.http.get(`${this.baseUrl}/udb/${networkId}/rt/${brandId}/${segment}/i.gif?userKey=${userKey}`,
            options).toPromise();
    }
}
