Placeholders are the way you insert live data values into the interface. You never type them by hand — you create them by picking a field from the Data Picker, and the builder inserts the placeholder for you. This page is a reference for what they look like, what they can target, and how they behave when the data they point at is missing.

## Basic Syntax

Throughout the docs, placeholders are shown using the readable shorthand `{{resource.key}}` — for example `{{deal.title}}` for a deal's title. This shorthand identifies *what the placeholder points at* and is the form most useful when reading or talking about a view.

The Data Picker actually inserts a longer named-field format under the hood — for example:

```
{{key: 'title', name: 'Title', resource: 'deal', variableType:'normal'}}
```

The runtime resolver reads the resource, key, and metadata directly from those named fields (`{{deal.title}}` written by hand would not resolve to anything because the parser does not find a `key:` or `resource:` to read). You never type this form yourself — the picker generates it and the slate editor displays it as a small badge.

The remainder of this page uses the shorthand for clarity.

Examples:

- `{{deal.title}}` — the deal's title
- `{{person.name}}` — the contact's name
- `{{user.email}}` — the logged-in Pipedrive user's email

## Mixing With Static Text

A single field can hold any combination of static text and placeholders:

```
Deal: {{deal.title}} ({{deal.value}} {{deal.currency}})
```

You can add as many placeholders as you like and type freely around them.

## Nested Fields (Dot Notation)

When a field contains a nested object, dot notation reaches deeper into it:

```
{{deal.owner_id.name}}
```

This first picks the `owner_id` object from the deal, then reads its `name` property. If any step of the path is missing, the placeholder resolves to an empty string (see [When Data Is Missing](#when-data-is-missing) below).

## What Placeholders Can Reference

Each placeholder starts with a **source** — the part before the first dot — that tells it where to look for the data. The sources match the tabs you see in the Data Picker:

| Source | What it reads |
|---|---|
| `deal` | Fields of the current Pipedrive deal |
| `organization` | Fields of the current organization |
| `person` | Fields of the current person |
| `user` | Fields of the logged-in Pipedrive user |
| `custom` | Anything the view's data source URL returned |
| `searchparams` | URL parameters passed into the view |
| `variable` | Interface variables you defined |
| `system` | The four System context values — `resource_id`, `resource`, `company_id` and `user_id` — offered by the **Context** tab |
| `view` | A View reference, also offered by the **Context** tab. It stores the id of another view of the same button and resolves to that id, so renaming the view changes nothing. In the builder, the Preview and the Test view a reference to a *deleted* view resolves to an empty string instead; the rendered view cannot tell and returns the id. |
| _(loop item)_ | The current iteration's data when the field sits inside a [looping area](/docs/buttons/interface-button/interface-builder/how-to/layout/areas#looping-an-area). The resource shorthand mirrors the loop's source (for example `{{deal.products.name}}` inside an area looping over `deal.products`); the synthetic `{{…index}}` resolves to the iteration number. |

On a [floating window button](/docs/buttons/interface-button/interface-builder/explanation/floating-window-buttons) the `deal`, `organization` and `person` sources have nothing to read and `system` carries only `company_id` and `user_id`, because that button's views get no Pipedrive record.

In addition, the Data Picker's **Functions** tab produces placeholders that run a built-in function (for example the current date) or a system text value — these are inserted the same way but carry their own logic instead of looking up a plain field.

## Inside an Input

Inside a Data Picker input, inserted placeholders look like small badges rather than raw `{{…}}` text. Backspace removes a badge as a whole, and you can type plain text freely before, between, and after them. The raw named-field syntax (see [Basic Syntax](#basic-syntax)) is what the slate field stores behind the scenes — you only see it if you export the view's data or look at it in the database.

## Placeholders Inside Tables

A Table block points its **Target Array** at an array. The table then renders one row per item in that array. Placeholders you put inside the table's columns resolve against the **current row's item** — not against the full resource. For example, if the array contains objects with a `name` field, you write `{{…name}}` in the column and each row shows its own value.

Placeholders that reference anything outside the array (for example `{{deal.title}}`) still resolve against the normal view-wide data. This lets you mix per-row values and view-wide values in the same table.

## When Data Is Missing

Placeholders never crash a view — they degrade quietly.

| Situation | What the placeholder becomes |
|---|---|
| The source (deal, person, custom, …) is not available | empty string |
| The field does not exist in the source | empty string |
| The field is present but its value is `null` | empty string |
| The field is an array (outside table context) | JSON text of the array |

So a missing field never shows `undefined` or an error — it just leaves a gap.

## Confidential Variables

Interface variables can be marked as confidential. A confidential variable never has its value exposed in the browser: the placeholder stays in its `{{…}}` form until the value is actually needed on the server side, where the substitution happens just before the value is used. This lets you reference things like API keys inside a URL or a header without them ever reaching the viewer's browser.
