Dynamic Linking is the way you connect dynamic data (both CMS and Variables) to content in your experience. Instead of typing a fixed value into a text field, you insert a token that pulls its value from somewhere exlse: a CMS field, a variable, the name of a linked target, and so on. When that source value changes, the content updates automatically everywhere it is used.

---

## **The Token Syntax**

Tokens follow the pattern `[source.field]`, where `source` is the data table or system you are pulling from, and `field`is the specific piece of data you want.

For example:

* `[hotspot.name]` inserts the name of the current hotspot from the CMS

* `[panorama.location]` inserts the location field of the current panorama

* `[var.brand_primary]` inserts the value of a variable named “Brand Primary”

---

## **Where You Can Use Tokens**

Tokens work in any text field that supports rich content. This includes hotspot labels, descriptions, tooltips, and custom HTML fields. When you are in one of these fields, type `[` to open the autocomplete menu. The menu shows all available sources and fields. You can keep typing to filter the list, then press Enter or click to insert the token.

---

## **Available Sources**

### **Hotspot**

Resolves fields from the current hotspot’s record in the Hotspots CMS table.

`[hotspot.name]`, `[hotspot.type]`, `[hotspot.panorama_name]`

Any custom field you have added to the Hotspots table is also available here.

### **Panorama**

Resolves fields from the current panorama’s record in the Panoramas CMS table.

`[panorama.name]`, `[panorama.location]`, `[panorama.time]`

Any custom field you have added to the Panoramas table is also available here.

### **Target**

Resolves the name of the panorama a navigation hotspot links to.

`[target.name]`

### **Group**

Resolves fields from the parent group hotspot’s record in the Group Hotspots CMS table. Useful when a hotspot is nested inside a group and you want to display information about that group.

`[group.name]`, `[group.panorama_name]`

You can also traverse up to a grandparent group using `[group.parent.field]`.

### **Collection**

Resolves fields from the currently active row inside a collection list component. This source is only available inside the content of a collection list, where each item represents one record from the connected CMS table.

`[collection.name]`, `[collection.price]`, `[collection.image]`

### **Variable**

Resolves the value of a project or craftspace variable.

`[var.brand_primary]`, `[var.border_radius]`

Variable names are normalized to snake_case. A variable named “Brand Primary” is referenced as `[var.brand_primary]`.

---

## **Linked Fields**

If a CMS table has a linked field pointing to another table, you can traverse that link inside a token using dot notation.

For example, if the Hotspots table has a linked field called “Status” that references a “Status” table with a “label” field, you can write:

`[hotspot.status.label]`

This resolves the label from the linked Status record for the current hotspot.

---

## **How Values Are Resolved**

**Numbers** are formatted according to the field’s settings, including decimal places, thousands separators, and separator style.

**Localizable fields** resolve to the value for the currently active language. If no translation exists for the active language, the default language value is used as a fallback.

**Image and audio fields** resolve to a working URL, so you can use them directly as the source of an image or audio element in custom HTML.

**Variables** resolve to their raw value: a hex code for a color variable, a pixel value for a number variable, and so on.

---

## **Tips**

* Use `[panorama.name]` in a hotspot label to automatically show the name of the destination panorama on a navigation hotspot, without ever typing it manually.

* Use `[collection.field]` inside a collection list to build a fully data-driven gallery or menu where every item is pulled from a CMS table.

* Localizable fields update automatically when the viewer switches language. You do not need separate tokens per language.


