---
title: "Adding a dataset | Customer&#x27;s Canvas Hub"
canonical: "https://customerscanvas.com/docs/hub/dev-center/scenarios/direct-mail/adding-a-dataset/"
---

# Adding a dataset

> Customer's Canvas uses an approach where VDP samples are stored in the design file. The saved samples will be applied to the design when rendering previews or print files.

The data is store as the `vdpDataSet` object, which may look as follows:

```json
{
  "vdpDataSet": { 
    "surfacesData": [ 
      { 
        "surfaceBinding": { 
          "surfaceIndexes": [ 0, 1 ],
          "isSingleBinding": false
        },
        "data": [
          {
            "Address": {
              "text": "Chloe Martin 2222 Cedar Lane Riverwood, TX 10987"
            },
            "Image": {
              "image": "https://example.com/8509328f.jpg"
            },
            "placeholders": {
              "Name": "John Wood",
              "Phone": "555-123-1234"
            }
          } 
        ], 
        "iterateOverSurfacesFirst": false 
      } 
    ] 
  }, 
  "vdpItemsData": null 
}
```

The endpoint [`PUT /api/atoms/v1/designs/{id}/vdp-data`](https://customerscanvas.com/docs/hub/dev-center/api/design-atoms.md#tag/designatomsservice/SaveVdpData) saves the VDP samples, while the endpoint [`GET /api/atoms/v1/designs/{id}/vdp-data`](https://customerscanvas.com/docs/hub/dev-center/api/design-atoms.md#tag/designatomsservice/LoadVdpData) reads them.

## Variable types

There are the following variable types:

- in-string placeholders
- interpolation text placeholders
- text placeholders
- images
- image placeholders
- barcode placeholders

When creating a dataset, different formats are used for different types:

- For text: `"Name": { "text": "John Wood" }`
- For in-string text: `"placeholders": { "Name": "John Wood" }`
- For barcode placeholders: `"URL": { "barcodeData": { "BarcodeFormat": "QR_CODE", "BarcodeSubType": "Url", "Url": "https://example.com" }}`
- For images and image placeholders:
    - private images from Asset Storage: `"Photo": { "image": "user:<Full path>" }`
    - public images from Asset Storage: `"Photo": { "image": "public:<Full path>" }`
    - external images: `"Photo": { "image": "<externalUrl>" }`

Here, `"Name"`, `"URL"`, and `"Photo"` are the field names. Note that the in-string and interpolation variables are placed in the `placeholders` collection, and all other variables are placed in the root of the data object.

A VDP dataset allows you to not only change the text and images, but also change their properties. For the complete list of variable properties, you can refer to the [ItemData description](https://customerscanvas.com/docs/hub/dev-center/scenarios/direct-mail/specifying-personalization-data.md) or to the [examples below](#itemdata-examples).

## Dataset properties

When a design contains a `vdpDataSet` object, the project only renders surfaces listed in the `surfacesData` collection with the applied items' `data`.

The `surfacesData` contains a list of required surfaces and items' data to personalize these surfaces. This `data` defines one or more objects that will be applied to render a single design copy. In `surfaceBinding`, you can refer to the required surfaces by either indexes or names.

```json
{
    "surfacesData": [{
        "surfaceBinding": {
            "surfaceNames": ["Front"]
        },
        "data": [{ ... }]
    }],
    "surfacesData": [{
        "surfaceBinding": {
            "surfaceIndexes": [0,1,2]
        },
        "data": [{
          ...
}
```

When you provide a number of data sets to render a number of surfaces, you can use the optional property `iterateOverSurfacesFirst` to configure the rendering order. If this property is `true`, then copies of the surfaces listed in the `surfaceBinding` are rendered in the following order:

1.  Render the first surface with the first data set.
2.  Render the first surface with the second data set.
3.  ... and so on for every data set.
4.  Render the second surface with the first data set.
5.  Render the second surface with the second data set.
6.  ... and so on for every surface and data set.

If `iterateOverSurfacesFirst` is `false` (this is the default value), then the personalization order goes over data sets:

1.  Render the first surface with the first data set.
2.  Render the second surface with the first data set.
3.  ... and so on for every surface.
4.  Render the first surface with the second data set.
5.  Render the second surface with the second data set.
6.  ... and so on for every surface and data set.

## ItemData examples

### Images with properties

In the following example, we define `data` to change the content of two image layers, the opacity, border width, and size.

```json
{
    "photo": {
        "image": "https://example.com/centralview.jpg",
        "opacity": 0.8,
        "borderWidth": 1
    },
    "cornerImage": {
        "image": "user:tower.jpg",
        "size": {
            "width": 100,
            "height": 100
        }
    }
}
```

### Image placeholders with transforms

For image placeholders, you can specify how their content should be resized. Also, you can scale, translate, and rotate the content.

```json
{
    "logo": {
        "image": "public:company/logo.svg",
        "contentResizeMode": "original",
        "contentTransform": {
            "angle": -45
        }
    },
    "photo": {
        "image": "https://example.com/castle.jpg",
        "contentResizeMode": "fill",
        "contentTransform": {
            "angle": 0,
            "scaleX": 0.5,
            "scaleY": 0.5,
            "translateX": 100,
            "translateY": 100
        }
    }
}
```

### Barcode placeholders

This example illustrates how you can set up linear barcodes in the EAN-8 format and QR codes for URLs and phone numbers.

```json
{
    "Ean 8": {
        "barcodeData": {
            "BarcodeFormat": "EAN_8",
            "BarcodeValue": "1234567"
        }
    },
    "URL": {
        "barcodeData": {
            "BarcodeFormat": "QR_CODE",
            "BarcodeSubType": "Url",
            "Url": "https://example.com"
        }
    },
    "Phone": {
        "barcodeData": {
            "BarcodeFormat": "QR_CODE",
            "BarcodeSubType": "Phone",
            "Phone": "5551234567"
        }
    }
}
```

### Interpolation placeholders

Let's assume your design contains the following text field.

`Dear {{Name}}, your order #{{Order}} is ready.`

Here, two interpolation placeholders are defined: `Name` and `Order`. To personalize their values, add their name and a new value to the `placeholders` object.

```json
{
    "placeholders": {
        "Name": "Cristopher Bennett",
        "Order": "200123"
    }
} 
```
