---
title: Recommendation batch publisher
description: Generate personalized recommendations in batches for email newsletters and offline scenarios.
slug: recommendations/batch-publisher
docKind: guide
hub: recommendations
---

Luigi's Box typically provides real-time recommendations through the Recommender API. However, for situations requiring recommendations for a large, defined user set at a scheduled time -- for example, sending personalized recommendations via newsletter -- Luigi's Box offers a Recommendation batch publisher service. This service can automatically create personalized recommendations in batches according to the configured schedule.

An important prerequisite is the use of Customer IDs in the analytics collection process. Customer IDs are identifiers of logged-in users. Check the Events API documentation to [learn how to track Customer IDs](/analytics/api/events/#common-parameters). Based on collected user data, the batch publisher can recommend personalized content for requested users.

The process for defining, generating, and retrieving a batch of published recommendations consists of the following steps:

1. The client defines the set of users to recommend for.
2. Luigi's Box sets up recommendation logics based on the client's preferences.
3. Luigi's Box sets up a recommendation batch publisher schedule based on the client's preferences.
4. Luigi's Box prepares and publishes recommendations at the scheduled time.
5. The integrated platform retrieves the generated recommendations.
6. The integrated platform distributes recommendations to customers.
7. Luigi's Box / client collects analytics data.

## Step 1 - The client defines the set of users to recommend for

Before a batch of recommendations can be prepared, the client needs to define the set of users to recommend for. Typically, the client defines a set of `customer_id` values depending on the integration.

Another option is to have Luigi's Box recommend for all known users whose `customer_id` was active in the past 6 months.

### SmartEmailing integration

For SmartEmailing integration, Luigi's Box retrieves the user list from the [SmartEmailing API](https://app.smartemailing.cz/docs/api/v3/index.html#api-Customfields-Get_Customfield_values) automatically. The client needs to tell Luigi's Box which field stores the user identifier.

### Klaviyo integration

Klaviyo has a [profiles API](https://developers.klaviyo.com/en/reference/get_profiles) for retrieving user data stored in the Klaviyo database. To match Klaviyo users with user profiles saved in the Luigi's Box database, the Luigi's Box `customer_id` needs to be saved in the Klaviyo user profile. The `customer_id` can be saved in any attribute under the `attributes.properties` structure.

For more information about `customer_id`, see [Events API common parameters](/analytics/api/events/#common-parameters).

### Other integrations

To integrate with other platforms, use the Batching users API to upload the set of users.

#### Batching users API

**POST** `https://live.luigisbox.com/v1/recommender/batching/<TRACKER_ID>/users`

:::caution
This endpoint requires HMAC authentication. See [API principles](/platform-foundations/api-principles/#authentication-hmac) for details.
:::

##### Request headers

| Header | Content |
| :--- | :--- |
| `Content-Type` | `multipart/form-data; boundary=sk13jk8sd823j9` |

When generating the HMAC token, the provided `Content-Type` should be `multipart/form-data`, without the boundary.

##### Request body

The request body is a file containing user IDs. File format details are described in [Import file format](#import-file-format).

| Form | Content |
| :--- | :--- |
| `file` | `@"/path/to/file.json"` |

For more information, see the [OpenAPI specification](/assets/openapi/batching-users-api.yaml).

##### Restrictions

1. Uploading a new file removes existing users for the specified tracker ID.
2. Uploaded files cannot be larger than 300 MB. Files exceeding this limit will be rejected. Reach out to [support@luigisbox.com](mailto:support@luigisbox.com) if you need to upload larger files.
3. An uploaded file must be fully transmitted within 10 minutes. If the upload takes longer than the 10-minute timeout limit, the server returns an error and cancels the upload. If you encounter issues while uploading, reach out to [support@luigisbox.com](mailto:support@luigisbox.com).

##### Import file format

The import file must be in JSON Lines or CSV format. It has one mandatory attribute, `auth_user_id`.

| Attribute | Description |
| :--- | :--- |
| `auth_user_id` | Required. ID of the user. Previously named `user_id`; the old name is still supported. |

Example of an import file in JSON Lines format:

```json
{"auth_user_id": "u123"}
{"auth_user_id": "u234"}
{"auth_user_id": "u345"}
```

Example of an import file in CSV format. The file should not contain a header. Each row contains the `auth_user_id` field:

```text
"u123"
"u234"
"u345"
```

## Step 2 - Luigi's Box sets up recommendation logics based on the client's preferences

The client defines business requirements based on which Luigi's Box prepares recommendation logics.

## Step 3 - Luigi's Box sets up a recommendation batch publisher schedule based on the client's preferences

The client defines how often recommendations for each logic should be generated.

## Step 4 - Luigi's Box prepares and publishes recommendations at the scheduled time

Using the recommendation batch publisher service, Luigi's Box prepares and publishes the recommendations according to the configured recommendation logics and schedule. However, certain integrations may require providing additional data for the batch generation process.

### SmartEmailing integration

The client provides a Luigi's Box username and API key for access to the SmartEmailing API.

### Klaviyo integration

To access and modify user profiles via the Klaviyo API, Luigi's Box requires a private key with the following permissions:

1. `lists:read`
2. `lists:write`
3. `profiles:read`
4. `profiles:write`

For more information about private keys, see the Klaviyo documentation about [private key authentication](https://developers.klaviyo.com/en/docs/authenticate_#private-key-authentication).

## Step 5 - The integrated platform retrieves the generated recommendations

For each user, recommendations contain a personalized list of results, typically products, for each recommender logic.

Recommendations are generated for users with interaction data from the past 6 months. In addition to personalized recommendation sets for the defined users, Luigi's Box also generates one generic set of non-personalized recommendations. It is stored under the key `default` and can be used for recommendations to new users, users without browsing history, users without cookie consent granted, and similar cases.

Batches of recommendations are generated at the highest configured frequency. For example, if `recommender_logic_1` is set to be generated biweekly and `recommender_logic_2` is set for weekly generation, Luigi's Box will generate recommendations for both logics on a weekly basis.

The format of recommendations and the way of retrieving data differ depending on the integration. Note that each result's `url` contains a tracking parameter named `recommendation_id`, generated by the recommender. This identifier is used by the analytics collector. See [Step 7](#step-7---luigis-box--client-collects-analytics-data).

### SmartEmailing integration

For SmartEmailing integration, the batch recommendation results are uploaded directly to the [SmartEmailing API](https://app.smartemailing.cz/docs/api/v3/index.html#api-Generic_collections) in JSON format. Luigi's Box creates a collection to which recommendations are uploaded.

#### Published recommendations JSON format

```json
{
  "id": "u123",
  "data": {
    "mail-recommender-1": [
      {
        "id": "product1-id",
        "url": "https://www.client-xyz.com/product1-url/?recommendation_id=1234abcd-7425-4fee-bed2-214dwxyz7890",
        "title": "Product 1",
        "image_link": "https://www.client-xyz.com/product1-img.jpg/"
      }
    ]
  }
}
```

### Klaviyo integration

Generated recommendations are uploaded directly to user profiles via the [Klaviyo API](https://developers.klaviyo.com/en/reference/spawn_bulk_profile_import_job). They are stored in JSON format under the `attributes.properties` structure of individual profiles.

As described above, Luigi's Box generates one set of non-personalized recommendations and saves it under the `default` profile. A Klaviyo profile is considered to be the default profile if its `attributes.external_id` attribute is equal to `default`. If no such profile is present, Luigi's Box automatically creates one.

#### Published recommendations JSON format

The following snippet shows a user profile with generated recommendations under the key `mail-recommender-1`.

```json
{
  "data": {
    "type": "profile",
    "id": "01GDDKASAP8TKDDA2GRZDSVP4H",
    "attributes": {
      "email": "sarah.mason@klaviyo-demo.com",
      "properties": {
        "mail-recommender-1": [
          {
            "id": "product1-id",
            "url": "https://www.client-xyz.com/product1-url/?recommendation_id=1234abcd-7425-4fee-bed2-214dwxyz7890",
            "title": "Product 1",
            "image_link": "https://www.client-xyz.com/product1-img.jpg/"
          }
        ]
      }
    }
  }
}
```

### Other integrations

To integrate with a platform other than SmartEmailing, contact Luigi's Box to obtain a link for accessing the generated recommendations in XML format.

#### Published recommendations XML format

Published recommendations have the following structure:

```xml
<?xml version="1.0" encoding="UTF-8"?>
<users>
  <user> ... </user>
  <user> ... </user>
  <user> ... </user>
</users>
```

Detailed structure of recommendations for one user:

```xml
<?xml version="1.0" encoding="UTF-8"?>
<users>
  <user>
    <auth_user_id>u123</auth_user_id>
    <data>
      <_metadata>
        <updated_at>2024-08-28T10:00:00</updated_at>
      </_metadata>
      <recommendations>
        <recommendation>
          <recommendation_type>mail-recommender-1</recommendation_type>
          <results>
            <result>
              <id>product1-id</id>
              <url>https://www.client-xyz.com/product1-url/?recommendation_id=1234abcd-7425-4fee-bed2-214dwxyz7890</url>
              <title>Product 1</title>
              <image_link>https://www.client-xyz.com/product1-img.jpg/</image_link>
            </result>
            <result>
              <id>product2-id</id>
              <url>https://www.client-xyz.com/product2-url/?recommendation_id=1234abcd-7425-4fee-bed2-214dwxyz7890</url>
              <title>Product 2</title>
              <image_link>https://www.client-xyz.com/product2-img.jpg/</image_link>
            </result>
          </results>
        </recommendation>
        <recommendation>
          <recommendation_type>mail-recommender-2</recommendation_type>
          <results>
            <result>
              <id>product3-id</id>
              <url>https://www.client-xyz.com/product3-url/?recommendation_id=wxyz7890-7425-4fee-bed2-214d1234abcd</url>
              <title>Product 3</title>
              <image_link>https://www.client-xyz.com/product3-img.jpg/</image_link>
            </result>
            <result>
              <id>product4-id</id>
              <url>https://www.client-xyz.com/product4-url/?recommendation_id=wxyz7890-7425-4fee-bed2-214d1234abcd</url>
              <title>Product 4</title>
              <image_link>https://www.client-xyz.com/product4-img.jpg/</image_link>
            </result>
          </results>
        </recommendation>
      </recommendations>
    </data>
  </user>
</users>
```

## Step 6 - The integrated platform distributes recommendations to customers

Luigi's Box only generates batch recommendations and does not handle delivery of the recommendations to end customers. Luigi's Box does not collect email addresses or any other contact data. The integrated platform is responsible for delivery.

## Step 7 - Luigi's Box / client collects analytics data

By default, the Luigi's Box analytics collector supports tracking recommendations from batch publishers. This is possible because the URLs of generated recommendations contain the `recommendation_id` parameter, for example `https://www.client-xyz.com/product1-url/?recommendation_id=1234abcd-7425-4fee-bed2-214dwxyz7890`. Based on these URLs, the Luigi's Box analytics collector on the client's website can collect user interactions with recommendations.

The analytics dashboard at `https://app.luigisbox.com/sites/<TRACKER_ID>/recommenders/analytics` then shows statistics for individual newsletter recommendations in the same way as for other models.

For a custom analytics integration, follow the [Events API documentation](/analytics/api/events/#impression-events) and pass the value of `recommendation_id` into the Impression analytics event.
