# Target Node.js SDK v1.0 released

[Target Node.js SDK](https://www.npmjs.com/package/@adobe/target-nodejs-sdk) v1.0 has been published and open-sourced.  
Please see the [CHANGELOG](https://github.com/adobe/target-nodejs-sdk/blob/master/CHANGELOG.md#101---2019-10-09) for
important notes on breaking changes and BatchMbox v2 API deprecation.  
This package is now **deprecated**, please use the new [@adobe/target-nodejs-sdk](https://www.npmjs.com/package/@adobe/target-nodejs-sdk)
NPM package instead.

# Adobe Target Node Client

The Adobe Target Node Client lets customers execute requests against the Adobe edge network and retrieve personalized 
content that can be used to enhance the user experience. 

Behind the scenes, the Target Node Client wraps two 
Adobe Marketing Cloud solutions:

 - The Marketing Cloud Identity Service (MCID), also known as the Visitor API
 - Adobe Target

## Super Simple to Use

The Target Node Client has been designed to be the simplest way to interact with the [Adobe Target batch delivery API](http://developers.adobetarget.com/api/#server-side-batch-delivery).

```js
const TargetNodeClient = require("@adobe/target-node-client");

const client = TargetNodeClient.create({
  config: {
    client: "acmeclient",
    organizationId: "1234567890@AdobeOrg",
    timeout: 5000
  }
});

const request = {
  payload: {
    mboxes: [{
      mbox: "server-side-mbox",
      indexId: 0
    }]
  }
};

client.getOffers(request)
.then(response => console.log('Response', response))
.catch(error => console.error('Error', error));
```

## Table of Contents

- [Adobe Target Node Client](#adobe-target-node-client)
  - [Super Simple to Use](#super-simple-to-use)
  - [Table of Contents](#table-of-contents)
  - [Target Only](#target-only)
  - [MCID Integration](#mcid-integration)
  - [MCID with Customer IDs Integration](#mcid-with-customer-ids-integration)
  - [MCID and Analytics Integration](#mcid-and-analytics-integration)
  - [Shared MCID and Analytics Integration](#shared-mcid-and-analytics-integration)
  - [MCID, Analytics and at.js Integration](#mcid-analytics-and-atjs-integration)
  - [Troubleshooting](#troubleshooting)
  - [Target Node Client API](#target-node-client-api)
      - [TargetNodeClient.create](#targetnodeclientcreate)
      - [TargetNodeClient.getOffer](#targetnodeclientgetoffer)
      - [TargetNodeClient.getOffers](#targetnodeclientgetoffers)


---


## Target Only

The Target Node Client can be used to retrieve personalized content from Target without being forced to use the MCID. 

```js
const TargetNodeClient = require("@adobe/target-node-client");

const client = TargetNodeClient.create({
  config: {
    client: "acmeclient",
    organizationId: "1234567890@AdobeOrg",
  }
});

const request = {
  payload: {
    mboxes: [{
      mbox: "server-side-mbox",
      indexId: 0
    }]
  }
};

client.getOffers(request)
.then(response => console.log('Response', response))
.catch(error => console.error('Error', error));
```

By default, the Target Node Client generates a new session ID for every Target call, which might not always be the desired behavior. To ensure that Target properly tracks the user session, you should ensure that the Target cookie is sent to the browser when Target content is retrieved and the Target cookie value is passed to `getOffer()` as a request is processed. 

In an `Express` application, this could look something like this:

```js
const express = require("express");
const cookieParser = require("cookie-parser");
const TargetNodeClient = require("@adobe/target-node-client");
const CONFIG = {
  client: "acmeclient",
  organizationId: "1234567890@AdobeOrg"
};

const app = express();
const client = TargetNodeClient.create({config: CONFIG});

app.use(cookieParser());

function saveCookie(res, cookie) {
  if (!cookie) {
    return;
  }

  res.cookie(cookie.name, cookie.value, {maxAge: cookie.maxAge * 1000});
}

function sendSuccessResponse(res, response) {
  res.set({
    "Content-Type": "text/html",
    "Expires": new Date().toUTCString()
  });

  saveCookie(res, response.targetCookie);

  res.status(200).send(response);
}

function sendErrorResponse(res, error) {
  res.set({
    "Content-Type": "text/html",
    "Expires": new Date().toUTCString()
  });

  res.status(500).send(error);
}

app.get("/abtest", function (req, res) {
  const targetCookieName = encodeURIComponent(TargetNodeClient.getTargetCookieName());
  const targetCookie = req.cookies[targetCookieName];
  const payload = {"mbox" : };
  const request = {
    payload: {
      mboxes: [{
        mbox: "server-side-mbox",
        indexId: 0
      }]
    }
  };

  console.log("Request", request);

  client.getOffers(request)
  .then(response => {
    sendSuccessResponse(res, response);
  })
  .catch(error => {
    sendErrorResponse(res, error);
  });
});

app.listen(3000, function () {
  console.log("Listening on port 3000 and watching!");
});
```

Full sample: https://github.com/Adobe-Marketing-Cloud/target-node-client-samples/tree/master/target-only

---


## MCID Integration

Although using the Target Node Client for fetching content from Target can be powerful, the added value of using MCID for user tracking outweighs using Target only. MCID allows leveraging all the goodies found in the Adobe Experience Cloud, such as audience sharing, analytics, etc. Using Target and MCID in an `Express` application is pretty straightforward. MCID has a client-side part, so we'll have to use a simple template that references the MCID JavaScript library. 

Here is the `Express` application:

```js
const express = require("express");
const cookieParser = require("cookie-parser");
const TargetNodeClient = require("@adobe/target-node-client");
const CONFIG = {
  client: "acmeclient",
  organizationId: "1234567890@AdobeOrg"
};
const TEMPLATE = `
<!doctype html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Target Node Client NodeJS SDK Sample</title>
  <script src="VisitorAPI.js"></script>
  <script>
    Visitor.getInstance("${organizationId}", {serverState: ${visitorState}});
  </script>
</head>
<body>
  <p>${content}</p>
</body>
</html>
`;

const app = express();
const client = TargetNodeClient.create({config: CONFIG});

app.use(cookieParser());
// We assume that VisitorAPI.js is stored in "public" folder
app.use(express.static(__dirname + "/public"));

function saveCookie(res, cookie) {
  if (!cookie) {
    return;
  }

  res.cookie(cookie.name, cookie.value, {maxAge: cookie.maxAge * 1000});
}

function sendSuccessResponse(res, response) {
  res.set({
    "Content-Type": "text/html",
    "Expires": new Date().toUTCString()
  });

  const result = TEMPLATE
  .replace("${organizationId}", CONFIG.organizationId)
  .replace("${visitorState}", JSON.stringify(response.visitorState))
  .replace("${content}", response.content);

  saveCookie(res, response.targetCookie);

  res.status(200).send(result);
}

function sendErrorResponse(res, error) {
  res.set({
    "Content-Type": "text/html",
    "Expires": new Date().toUTCString()
  });

  res.status(500).send(error);
}

app.get("/abtest", function (req, res) {
  const visitorCookieName = encodeURIComponent(TargetNodeClient.getVisitorCookieName(CONFIG.organizationId));
  const visitorCookie = req.cookies[visitorCookieName];
  const targetCookieName = encodeURIComponent(TargetNodeClient.getTargetCookieName());
  const targetCookie = req.cookies[targetCookieName];
  const payload = {
      mboxes: [{
        mbox: "server-side-mbox",
        indexId: 0
      }]
    }
  };
  const request = Object.assign({payload}, {targetCookie}, {visitorCookie});

  console.log("Request", request);

  client.getOffers(request)
  .then(response => {
    sendSuccessResponse(res, response);
  })
  .catch(error => {
    sendErrorResponse(res, error);
  });
});

app.listen(3000, function () {
  console.log("Listening on port 3000 and watching!");
});
```

The biggest benefit of using the MCID integration is that it allows you to share Audience Manager segments with Target. Because
this is a server-side integration for first-time visitors, you might not have any Audience Manager related data.

Full sample: https://github.com/Adobe-Marketing-Cloud/target-node-client-samples/tree/master/mcid-integration

---

## MCID with Customer IDs Integration

Sometimes when you have logged details, you could be more specific and pass the logged details via `customerIds`. The `customerIds` object is similar to the MCID functionality described here: https://marketing.adobe.com/resources/help/en_US/mcvid/mcvid-authenticated-state.html.

Here is the `Express` application that shows `customerIds` in action:

```js
const express = require("express");
const cookieParser = require("cookie-parser");
const TargetNodeClient = require("@adobe/target-node-client");
const CONFIG = {
  client: "acmeclient",
  organizationId: "1234567890@AdobeOrg"
};
const TEMPLATE = `
<!doctype html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Target Node Client NodeJS SDK Sample</title>
  <script src="VisitorAPI.js"></script>
  <script>
    Visitor.getInstance("${organizationId}", {serverState: ${visitorState}});
  </script>
</head>
<body>
  <p>${content}</p>
</body>
</html>
`;

const app = express();
const client = TargetNodeClient.create({config: CONFIG});

app.use(cookieParser());
// We assume that VisitorAPI.js is stored in "public" folder
app.use(express.static(__dirname + "/public"));

function saveCookie(res, cookie) {
  if (!cookie) {
    return;
  }

  res.cookie(cookie.name, cookie.value, {maxAge: cookie.maxAge * 1000});
}

function sendSuccessResponse(res, response) {
  res.set({
    "Content-Type": "text/html",
    "Expires": new Date().toUTCString()
  });

  const result = TEMPLATE
  .replace("${organizationId}", CONFIG.organizationId)
  .replace("${visitorState}", JSON.stringify(response.visitorState))
  .replace("${content}", response.content);

  saveCookie(res, response.targetCookie);

  res.status(200).send(result);
}

function sendErrorResponse(res, error) {
  res.set({
    "Content-Type": "text/html",
    "Expires": new Date().toUTCString()
  });

  res.status(500).send(error);
}

app.get("/abtest", function (req, res) {
  const visitorCookieName = encodeURIComponent(TargetNodeClient.getVisitorCookieName(CONFIG.organizationId));
  const visitorCookie = req.cookies[visitorCookieName];
  const targetCookieName = encodeURIComponent(TargetNodeClient.getTargetCookieName());
  const targetCookie = req.cookies[targetCookieName];
  const customerIds = {
    "userid": {
      "id": "67312378756723456",
      "authState": TargetNodeClient.AuthState.AUTHENTICATED
    }
  };
  const payload = {
      mboxes: [{
        mbox: "server-side-mbox",
        indexId: 0
      }]
    }
  };
  const request = Object.assign({customerIds}, {payload}, {targetCookie}, {visitorCookie});

  console.log("Request", request);

  client.getOffers(request)
  .then(response => {
    sendSuccessResponse(res, response);
  })
  .catch(error => {
    sendErrorResponse(res, error);
  });
});

app.listen(3000, function () {
  console.log("Listening on port 3000 and watching!");
});
```

Full sample: https://github.com/Adobe-Marketing-Cloud/target-node-client-samples/tree/master/mcid-customer-ids-integration

---


## MCID and Analytics Integration

To get the most out of the Target Node Client and to use the powerful analytics capabilities provided by Adobe Analytics, you can use the MCID, Analytics, and Target combo. 

Here is a simple `Express` application that demonstrates how you can use all three solutions in a single application: 

```js
const express = require("express");
const cookieParser = require("cookie-parser");
const TargetNodeClient = require("@adobe/target-node-client");
const CONFIG = {
  client: "acmeclient",
  organizationId: "1234567890@AdobeOrg"
};
const TEMPLATE = `
<!doctype html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Target Node Client NodeJS SDK Sample</title>
  <script src="VisitorAPI.js"></script>
  <script>
    Visitor.getInstance("${organizationId}", {serverState: ${visitorState}});
  </script>
</head>
<body>
  <p>${content}</p>
  <script src="AppMeasurement.js"></script>
  <script>var s_code=s.t();if(s_code)document.write(s_code);</script>
</body>
</html>
`;

const app = express();
const client = TargetNodeClient.create({config: CONFIG});

app.use(cookieParser());
// We assume that VisitorAPI.js and AppMeasurement.js is stored in "public" folder
app.use(express.static(__dirname + "/public"));

function saveCookie(res, cookie) {
  if (!cookie) {
    return;
  }

  res.cookie(cookie.name, cookie.value, {maxAge: cookie.maxAge * 1000});
}

function sendSuccessResponse(res, response) {
  res.set({
    "Content-Type": "text/html",
    "Expires": new Date().toUTCString()
  });

  const result = TEMPLATE
  .replace("${organizationId}", CONFIG.organizationId)
  .replace("${visitorState}", JSON.stringify(response.visitorState))
  .replace("${content}", response.content);

  saveCookie(res, response.targetCookie);

  res.status(200).send(result);
}

function sendErrorResponse(res, error) {
  res.set({
    "Content-Type": "text/html",
    "Expires": new Date().toUTCString()
  });

  res.status(500).send(error);
}

app.get("/abtest", function (req, res) {
  const visitorCookieName = encodeURIComponent(TargetNodeClient.getVisitorCookieName(CONFIG.organizationId));
  const visitorCookie = req.cookies[visitorCookieName];
  const targetCookieName = encodeURIComponent(TargetNodeClient.getTargetCookieName());
  const targetCookie = req.cookies[targetCookieName];
  const payload = {
      mboxes: [{
        mbox: "server-side-mbox",
        indexId: 0
      }]
    }
  };
  const request = Object.assign({payload}, {targetCookie}, {visitorCookie});

  console.log("Request", request);

  client.getOffers(request)
  .then(response => {
    sendSuccessResponse(res, response);
  })
  .catch(error => {
    sendErrorResponse(res, error);
  });
});

app.listen(3000, function () {
  console.log("Listening on port 3000 and watching!");
});
```

Using MCID, Analytics, and Target lets you:
- Use segments from Audience Manager
- Customize the user experience based on the content retrieved from Target
- Ensure that all events and success metrics are collected in Analytics
- Use Analytics' powerful queries and benefit from awesome visualizations

Full sample: https://github.com/Adobe-Marketing-Cloud/target-node-client-samples/tree/master/mcid-analytics-integration

---


## Shared MCID and Analytics Integration

By default, the Target Node Client instantiates a new Visitor instance on each `getOffer` or `getOffers` call.  
In cases when the same Visitor instance needs to be shared across several Target Node Client API calls, this can be 
achieved by explicitly initializing the Visitor instance and passing it in `getOffer`/`getOffers` calls as a `request` parameter.    

Check out the sample here: https://github.com/Adobe-Marketing-Cloud/target-node-client-samples/tree/master/shared-mcid-analytics-integration

---


## MCID, Analytics and at.js Integration

Most of the time the Target Node Client will be used in a NodeJS application, such as `Express`, `Hapi`, `Koa`, etc. However, with the recent proliferation of frameworks that allow server-side rendering (such as Facebook React or Angular 4.x), there are use cases where server-side should be aware and work in tandem with client-side libraries. In Target's case the client-side library is `at.js`.

The integration between server-side and client-side is also known as "hybrid" testing mode. The biggest challenge when trying to integrate server-side and client-side is to ensure that both server-side and client-side Target calls are hitting the same Target edge cluster. Otherwise you might end up with different user profiles being created by server-side and client-side calls.

To mitigate this situation, Target uses the so-called location hint cookie. To be able to use the location hint cookie you must add the following JavaScript to your HTML page before `at.js` or make sure that this code is executed before `at.js`, if you are using a tag manager such as `Adobe Launch`.

```js
window.targetGlobalSettings = {
  overrideMboxEdgeServer: true
};
```

To see the Target location hint cookie and `at.js` integration in action, here is a simple `Express` application:

```js
const express = require("express");
const cookieParser = require("cookie-parser");
const TargetNodeClient = require("@adobe/target-node-client");
const CONFIG = {
  client: "acmeclient",
  organizationId: "1234567890@AdobeOrg"
};
const TEMPLATE = `
<!doctype html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Target Node Client NodeJS SDK Sample</title>
  <script src="VisitorAPI.js"></script>
  <script>
    Visitor.getInstance("${organizationId}", {serverState: ${visitorState}});
  </script>
  <script>
    window.targetGlobalSettings = {
      overrideMboxEdgeServer: true
    };
  </script>
  <script src="at.js"></script>
</head>
<body>
  <p>${content}</p>
  <script src="AppMeasurement.js"></script>
  <script>var s_code=s.t();if(s_code)document.write(s_code);</script>
</body>
</html>
`;

const app = express();
const client = TargetNodeClient.create({config: CONFIG});

app.use(cookieParser());
// We assume that VisitorAPI.js, at.js and AppMeasurement.js is stored in "public" folder
app.use(express.static(__dirname + "/public"));

function saveCookie(res, cookie) {
  if (!cookie) {
    return;
  }

  res.cookie(cookie.name, cookie.value, {maxAge: cookie.maxAge * 1000});
}

function sendSuccessResponse(res, response) {
  res.set({
    "Content-Type": "text/html",
    "Expires": new Date().toUTCString()
  });

  const result = TEMPLATE
  .replace("${organizationId}", CONFIG.organizationId)
  .replace("${visitorState}", JSON.stringify(response.visitorState))
  .replace("${content}", response.content);

  saveCookie(res, response.targetCookie);
  saveCookie(res, response.targetLocationHintCookie);

  res.status(200).send(result);
}

function sendErrorResponse(res, error) {
  res.set({
    "Content-Type": "text/html",
    "Expires": new Date().toUTCString()
  });

  res.status(500).send(error);
}

app.get("/abtest", function (req, res) {
  const visitorCookieName = encodeURIComponent(TargetNodeClient.getVisitorCookieName(CONFIG.organizationId));
  const visitorCookie = req.cookies[visitorCookieName];
  const targetCookieName = encodeURIComponent(TargetNodeClient.getTargetCookieName());
  const targetCookie = req.cookies[targetCookieName];
  const targetLocationHintCookieName = encodeURIComponent(TargetNodeClient.getTargetLocationHintCookieName());
  const targetLocationHintCookie = req.cookies[targetLocationHintCookieName];
  const payload = {
      mboxes: [{
        mbox: "server-side-mbox",
        indexId: 0
      }]
    }
  };
  const request = Object.assign({payload}, {targetCookie}, {visitorCookie}, {targetLocationHintCookie});

  console.log("Request", request);

  client.getOffers(request)
  .then(response => {
    sendSuccessResponse(res, response);
  })
  .catch(error => {
    sendErrorResponse(res, error);
  });
});

app.listen(3000, function () {
  console.log("Listening on port 3000 and watching!");
});
```

Using the `at.js` integration allows use cases where a Target experience is started on the server-side and is continued on the client-side by `at.js`, also known as "hybrid" testing. The downside of this approach is that you might see some performance degradations when a NodeJS application that uses the Target Node Client is not geo-distributed as Target edge clusters.

Full sample: https://github.com/Adobe-Marketing-Cloud/target-node-client-samples/tree/master/mcid-analytics-atjs-integration

---

## Troubleshooting

The Target Node Client is a glorified HTTP/HTTPS client, so to understand what is happening on the wire, you can provide a `logger` object. The `logger` object is expected to have a `log()` method that receives a list of parameters. The default `logger` has a noop `log()` implementation. To be able to inspect the HTTP request and response, you can provide a custom `logger`. 

Here is an example that shows a `logger` that logs everything to `console`:

```js
const fs = require("fs");
const express = require("express");
const cookieParser = require("cookie-parser");
const TargetNodeClient = require("../lib/index");

const CONFIG = {
  client: "acmeclient",
  organizationId: "1234567890@AdobeOrg",
};

const logger = getLogger();

function getLogger() {
  return {
    log: function(...arr) {
      console.log(...arr);
    }
  };
}

function createTargetNodeClient(logger, config) {
  const options = Object.assign({logger}, {config});

  return TargetNodeClient.create(options);
}

const client = createTargetNodeClient(logger, CONFIG);

client.getOffers({
  payload: {
    mbox : "some-mbox"
  }
})
.then(response => console.log('Response', response))
.catch(error => console.error('Error', error));
```

If you want to use a more robust `logger`, you can always create a logger that delegates to `winston`, `bunyan`, or any other well-known NodeJS logging library.

If you are interested in using Target trace functionality you could try using the sample: https://github.com/Adobe-Marketing-Cloud/target-node-client-samples/tree/master/target-traces

---


## Target Node Client API 

#### TargetNodeClient.create

`TargetNodeClient.create(options: Object): TargetNodeClient` creates an instance of the Target Node Client. 
 
The `options` object has the following structure:
 
| Name                    | Type   |Required | Default | Description       |
|-------------------------|--------|---------|---------|-------------------|
| config                  | Object | Yes     | None    | General config    |
| logger                  | Object | No      | NOOP    | Logger to be used | 

The `config` object should have the following structure:

| Name            | Type     |Required | Default                | Description                            |
|-----------------|----------|---------|------------------------|----------------------------------------|
| client          |  String  | Yes     | None                   | Target client                          |
| organizationId  |  String  | Yes     | None                   | Organization ID                        |
| timeout         |  Number  | No      | None                   | Target request timeout in milliseconds |
| serverDomain    |  String  | No      | `client`.tt.omtrdc.net | Overrides default hostname             |

`TargetNodeClient.getVisitorCookieName(organizationId: string): string` is used to retrieve the MCID cookie name.
 
`TargetNodeClient.getTargetCookieName(): string` is used to retrieve the Target cookie name.

`TargetNodeClient.getTargetLocationHintCookieName(): string` is used to retrieve the Target location hint cookie name.

#### TargetNodeClient.getOffer

`TargetNodeClient.getOffer(request: Object): Promise` is used to fetch a single offer from Target.

The `request` object has the following structure:

| Name                     | Type     | Required  | Default | Description                                 |
|--------------------------|----------|-----------|---------|---------------------------------------------|
| sessionId                | String   |  No       | None    | Used when sending multiple mbox requests    |
| payload                  | Object   |  Yes      | None    | Server-Side Delivery API payload            |
| customerIds              | Object   |  No       | None    | Used to add additional user IDs             |
| targetCookie             | String   |  No       | None    | Target cookie                               |
| targetLocationHintCookie | String   |  No       | None    | Target location hint cookie                 |
| visitorCookie            | String   |  No       | None    | Visitor cookie                              |
| traceToken               | String   |  No       | None    | Used to pass mbox trace authorization token |

NOTE: `sessionId` is not required for single mbox request, however when you want to fetch content for multiple mboxes that should be displayed in HTML page, then we have to use `sessionId`. This will ensure that mbox requests will use the same profile.

To learn more about the Target Server-Side Delivery API, see http://developers.adobetarget.com/api/#server-side-delivery

The `promise` returned by `TargetNodeClient.getOffer(...)` wraps an `offer`. 

The `offer` object has the following structure:

| Name                     | Type              | Description                                                 |
|--------------------------|-------------------|-------------------------------------------------------------|
| targetCookie             | Object            | Target cookie                                               |
| targetLocationHintCookie | Object            | Target location hint cookie                                 |
| visitorState             | Object            | Object that should be passed to Visitor API `getInstance()` |
| content                  | String or Object  | Personalized content, can be string or object               |
| responseTokens           | Object            | Offer's response tokens                                     |
| trace                    | Object            | Available when using mbox trace functionality               |

The `cookie` object used for passing data back to the browser has the following structure:

| Name   | Type   | Description                                                                                               |
|--------|--------|-----------------------------------------------------------------------------------------------------------|
| name   | String | Cookie name                                                                                               |
| value  | Any    | Cookie value, the value will converted to string                                                          |
| maxAge | Number | The `maxAge` option is a convenience option for setting `expires` relative to the current time in seconds |


#### TargetNodeClient.getOffers

`TargetNodeClient.getOffers(request: Object): Promise` is used to fetch multiple offers from Target in a batch request.

The `request` object has the following structure:

| Name                     | Type     | Required  | Default | Description                                 |
|--------------------------|----------|-----------|---------|---------------------------------------------|
| sessionId                | String   |  No       | None    | Used when sending multiple mbox requests    |
| payload                  | Object   |  Yes      | None    | Server-Side Delivery Batch API payload      |
| customerIds              | Object   |  No       | None    | Used to add additional user IDs             |
| targetCookie             | String   |  No       | None    | Target cookie                               |
| targetLocationHintCookie | String   |  No       | None    | Target location hint cookie                 |
| visitorCookie            | String   |  No       | None    | Visitor cookie                              |
| traceToken               | String   |  No       | None    | Used to pass mbox trace authorization token |

NOTE: `sessionId` is not required for a single-batch mbox request; however, when you want to fire multiple batch requests, then we have to use `sessionId`. This will ensure that mbox requests will use the same profile.

The `payload` at the very least should contain an `mboxes` array. Each `mbox` object from `mboxes` array should have the following structure:

| Name                     | Type            | Required  | Default | Description                                       |
|--------------------------|-----------------|-----------|---------|---------------------------------------------------|
| indexId                  | Integer         |  Yes      | None    | Mboxes are processed in order determined by it    |
| mbox                     | String          |  Yes      | None    | Mbox name                                         |
| parameters               | Object          |  No       | None    | Mbox parameters                                   |

Note: `customerIds` object is used to provide additional data about users. More detailed description can be found [here](https://marketing.adobe.com/resources/help/en_US/mcvid/mcvid-authenticated-state.html) and [here's an example](http://developers.adobetarget.com/api/#batch-input-parameters).


To learn more about the Target Server-Side Batch Delivery API, see http://developers.adobetarget.com/api/#batch-overview


The `promise` returned by `TargetNodeClient.getOffers(...)` wraps the response returned by the Target Server-Side Batch Delivery API. It has the following structure:

| Name                     | Type              | Description                                                 |
|--------------------------|-------------------|-------------------------------------------------------------|
| targetCookie             | Object            | Target cookie                                               |
| targetLocationHintCookie | Object            | Target location hint cookie                                 |
| visitorState             | Object            | Object that should be passed to Visitor API `getInstance()` |
| content                  | Object            | Batch Delivery API response content                         |
| trace                    | Object            | Available when using mbox trace functionality               |

The `content` object has the following properties:

| Name                     | Type              | Description                                                 |
|--------------------------|-------------------|-------------------------------------------------------------|
| requestId                | String            | ID of the request                                           |
| id                       | Object            | User IDs like tntId, thirdPartyId, etc                      |
| client                   | String            | Target client code                                          |
| mboxResponses            | Array             | The array of retrieved mboxes                               |
| contentAsJson            | Boolean           | It has same value as provided in request                    |
| trace                    | Object            | Available when using mbox trace functionality               |

Each `mbox` object from `mboxResponses` array has the following structure:

| Name                     | Type              | Description                                                 |
|--------------------------|-------------------|-------------------------------------------------------------|
| mbox                     | String            | Mbox name                                                   |
| content                  | String | Object   | Offer content                                               |
| responseTokens           | Object            | Offer's response tokens                                     |
| trace                    | Object            | Available when using mbox trace functionality               |

The `cookie` object used for passing data back to the browser has the following structure:

| Name   | Type   | Description                                                                                               |
|--------|--------|-----------------------------------------------------------------------------------------------------------|
| name   | String | Cookie name                                                                                               |
| value  | Any    | Cookie value, the value will converted to string                                                          |
| maxAge | Number | The `maxAge` option is a convenience option for setting `expires` relative to the current time in seconds |

[back to top](#table-of-contents)
