> For the complete documentation index, see [llms.txt](https://help.gleantap.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://help.gleantap.com/campaigns/dynamic-content-with-special-attributes.md).

# Dynamic Content with Special Attributes

How to use Special Attributes to swap content — addresses, links, images, offers — per recipient inside a single email or SMS, so one campaign or flow can serve every location.

Most merge tags pull a value that already exists on the contact record — `{first_name}`, `{last_visit_date}`, `{workroom_name}`. A **Special Attribute** is a merge tag *you* define, where **you** decide the value based on filters.

You write the rule once:

> If the contact's location is **Northside**, this tag means `1420 Oak St, Suite 3` — otherwise it means `88 Harbor Ave`.

Then you drop `{location_address}` into an email or SMS. Every recipient gets the right address, from one message.

**This is what lets you run one campaign, one template, and one flow across every location** instead of building and maintaining a near-identical copy per club.

Special Attributes aren't limited to locations. Anything you can express as a filter can drive the swap: membership tier, coach, lead source, plan type, sign-up date range.

***

## How it works

A Special Attribute has three parts:

| Part              | What it does                                                                                                                |
| ----------------- | --------------------------------------------------------------------------------------------------------------------------- |
| **Label**         | The tag name. You insert it into messages as `{Label}`.                                                                     |
| **Default Value** | What the tag resolves to when no filter matches. Required — it's your safety net.                                           |
| **Filters**       | An ordered list. Each filter pairs a **value** with **criteria**. If a recipient matches the criteria, they get that value. |

At send time, for each recipient:

1. Gleantap walks the filters **in order** — Filter #1, then #2, then #3.
2. The **first** filter whose criteria the contact matches wins. Its value is substituted and the rest are skipped.
3. If no filter matches, the **Default Value** is used.

Two consequences worth internalizing:

* **Order matters.** Put your most specific filters first. If Filter #1 is broad enough to catch everyone, Filters #2 and #3 will never fire.
* **Nobody gets a blank.** Because the Default Value is required, every recipient resolves to something. Make the default the value that's safest to send to a contact whose location or tier you don't know — usually your main location or a generic link.

***

## Creating a Special Attribute

**Step 1** — Click the **gear icon** at the top-right of the app, then **Configure Workroom**.

**Step 2** — In the **Workroom Settings** menu on the left, click **Special Attribute**. You'll see a table of existing attributes with their Label and Value.

**Step 3** — Click **New Attribute**.

**Step 4** — Enter a **Label**. This is the tag name you'll type into messages.

> Labels can only contain letters, numbers, underscores, periods, and hyphens — **no spaces**. `location_address` works; `Location Address` is rejected. Labels must also be unique within the workroom.

**Step 5** — Enter a **Default Value**. This is what recipients get when none of your filters match.

**Step 6** — Click **Add Filter**. A **Filter #1** card appears.

**Step 7** — In the card, enter the **Value** this filter should produce, then click **Update Condition**.

**Step 8** — In the **Add Condition** panel, click **Add Filter** to add criteria rows, build your condition (for example, `Location` `is` `Northside`), and click **Save**.

**Step 9** — Repeat Steps 6-8 for each additional variant.

**Step 10** — Click **Create**.

The attribute is immediately available in every message editor in that workroom.

**Note on criteria:** the condition builder is the same one used for segments — the same attributes, events, pipeline stages, form responses, purchases, and loyalty criteria are available. See [Filter Options](/audience/creating-segments/filter-options.md) for operator semantics. All criteria you add to a single filter must be true for that filter to match. To express an either/or, create two filters that produce the same value.

***

## Using it in messages

Once created, the attribute shows up in the **Special Attributes** group of every merge-tag picker.

| Where                         | How to insert                                                             |
| ----------------------------- | ------------------------------------------------------------------------- |
| **SMS campaign**              | Click **Personalize** → **Special Attributes** → pick your attribute      |
| **Email campaign / template** | Open the merge-tag dropdown in the content block → **Special Attributes** |
| **Flow email and SMS steps**  | Same merge-tag picker inside the step editor                              |
| **Inbox**                     | Click the `{}` icon in the message composer                               |
| **Landing pages**             | Merge-tag menu in the page builder                                        |

In every case the tag is inserted as `{Label}` and resolves per recipient when the message actually sends.

### Swapping links

If your Special Attribute's **Default Value** is a URL, it also appears in the email builder's link dropdown under **Managed** links. Select it when linking a button or text, and each recipient's button points at their own destination — their location's booking page, their studio's schedule, their gym's Google review link.

In SMS, a URL that comes from a Special Attribute is shortened and click-tracked like any other link in the message.

### Swapping images

Put `{Label}` in an image's URL field instead of a fixed image address. Set the attribute's default and filter values to the full image URLs you want, and the image itself changes per recipient — a location photo, a coach headshot, a tier-specific offer graphic.

***

## Worked example — one email for five locations

You run five studios in one workroom. Contacts carry a `Location` attribute (see [Managing Multiple Locations](/settings/managing-multiple-locations.md)). You want a single monthly newsletter.

**Create three Special Attributes:**

`location_address`

|             | Value                                          | Criteria              |
| ----------- | ---------------------------------------------- | --------------------- |
| Filter #1   | `1420 Oak St, Suite 3`                         | Location is Northside |
| Filter #2   | `88 Harbor Ave`                                | Location is Harbor    |
| Filter #3   | `2200 Mill Rd`                                 | Location is Millbrook |
| **Default** | `Find your studio at ourstudios.com/locations` | —                     |

`location_booking_link`

|             | Value                                   | Criteria              |
| ----------- | --------------------------------------- | --------------------- |
| Filter #1   | `https://book.ourstudios.com/northside` | Location is Northside |
| Filter #2   | `https://book.ourstudios.com/harbor`    | Location is Harbor    |
| Filter #3   | `https://book.ourstudios.com/millbrook` | Location is Millbrook |
| **Default** | `https://book.ourstudios.com`           | —                     |

`location_photo`

|             | Value                                           | Criteria              |
| ----------- | ----------------------------------------------- | --------------------- |
| Filter #1   | `https://cdn.ourstudios.com/img/northside.jpg`  | Location is Northside |
| Filter #2   | `https://cdn.ourstudios.com/img/harbor.jpg`     | Location is Harbor    |
| **Default** | `https://cdn.ourstudios.com/img/brand-hero.jpg` | —                     |

**Then build one email:**

* Hero image URL → `{location_photo}`
* Footer address line → `{location_address}`
* "Book a class" button → the **Managed** link `location_booking_link`

One campaign. One send. Five versions delivered.

**When you open a sixth studio,** you add one filter to each attribute. You don't touch the email, the template, or any flow that uses it.

***

## Worked example — beyond locations

The same mechanic works on anything filterable.

`renewal_offer` — a different incentive by membership tier:

|             | Value                  | Criteria                    |
| ----------- | ---------------------- | --------------------------- |
| Filter #1   | `2 free PT sessions`   | Membership type is Elite    |
| Filter #2   | `1 free guest pass`    | Membership type is Standard |
| **Default** | `10% off your renewal` | —                           |

`assigned_coach_name` — pulled from a pipeline or attribute condition, so a nurture flow signs off with the right person.

`front_desk_phone` — so "reply or call us at {front\_desk\_phone}" reaches the right desk.

***

## Testing before you send

**Preview as a real contact.** In the campaign preview, search for and select a specific member. The preview resolves that contact's filters and shows exactly what they'd receive. Try one contact per variant plus one contact that matches nothing, so you see your Default Value render too.

**A preview or test send with no contact selected shows the Default Value for every Special Attribute.** That's expected — with no recipient, there's nothing to filter on. If you test only this way, you'll never see your filters work. Always preview as a specific contact.

See [Sending a Test](/campaigns/sending-a-test.md).

***

## Editing and deleting

Open **Configure Workroom → Special Attribute** and use the pencil icon to edit or the trash icon to delete.

**Edits take effect on the next send.** Changing a value updates every campaign, template, flow, and page that references the tag — that's the point. Messages already sent aren't retroactively changed.

**Deleting an attribute that's still in use is destructive.** The tag stops resolving, and `{Label}` is delivered as literal text in the message body. Before deleting, search your templates, campaigns, and flow steps for the tag. The same applies to typos — a misspelled tag isn't recognized, so it goes out as-is.

**Filters can't be reordered** once saved. To change the order, delete the filter and re-add it in the position you want. Because the first match wins, this occasionally matters — plan the order when you build it.

***

## Common scenarios

### "Everyone got the same address, not their location's"

Three things to check, in order:

1. **Did you preview with a contact selected?** A preview with no contact always shows defaults. This is the most common cause.
2. **Do your contacts actually have the attribute the filter tests?** If `Location` is blank on a contact, no location filter matches and they fall through to the default. Build a segment on that criterion and check the count — if it returns 0 or far fewer than expected, the data isn't there. See [Filter Options](/audience/creating-segments/filter-options.md).
3. **Is Filter #1 too broad?** First match wins. A filter that catches everyone starves the ones below it.

### "The email shows `{location_address}` as literal text"

The tag doesn't match any Special Attribute in that workroom. Either the label is misspelled in the message, the attribute was deleted, or you're sending from a different workroom than the one where you created it. Labels are case-sensitive and space-free.

### "I created it but it's not in the merge-tag list"

Special Attributes are **workroom-scoped**. If you run one workroom per location (Pattern A in [Managing Multiple Locations](/settings/managing-multiple-locations.md)), the attribute exists only in the workroom where you created it — you'd need to recreate it in each. Note that Pattern A rarely needs Special Attributes for location content in the first place; each workroom's messages are already location-specific. Special Attributes pay off most in Pattern B, where all locations share one workroom.

### "Can a Special Attribute contain another merge tag?"

No. A value like `Call {first_name} at 555-0100` is delivered literally — nested tags inside a Special Attribute value aren't resolved. Keep the tags side by side in the message instead: `Hi {first_name}, call us at {front_desk_phone}`.

### "My SMS credit usage went up after adding a Special Attribute"

The resolved value counts toward the message length, and it differs per recipient. If one location's address is 20 characters longer than another's, those recipients may cross the 160-character line into a second segment. Check your longest filter value against your message length. See [Billing](/settings/billing.md).

### "Can I use one for a subject line?"

Yes — the subject line supports the same merge tags as the body.

### "I don't see the Special Attribute tab"

You need Configuration → Workroom permission. Admin and Workroom Admin have it by default; custom roles may not. See [Roles & Permissions Reference](/settings/add-remove-sub-users/roles-and-permissions-reference.md).

### "How many filters can one attribute have?"

There's no set limit. In practice, if you're past a dozen you're probably encoding something that belongs on the contact record as an attribute instead — then a single `{attribute}` tag does the job with no filters at all.

***

## Special Attributes vs. contact attributes

Use a **contact attribute** (Configure Workroom → Attribute) when the value genuinely belongs to the person and is already in your data — their coach, their plan name, their join date. Insert it directly as a merge tag.

Use a **Special Attribute** when the value belongs to *you*, not the contact — an address, a booking URL, an image, an offer — and which one they get depends on a condition. The contact record has no field for "the booking link for the studio this member belongs to"; a Special Attribute is where that mapping lives.

***

## Related pages

* [Managing Multiple Locations](/settings/managing-multiple-locations.md) — the two multi-location patterns and how location gets set on a contact
* [Filter Options](/audience/creating-segments/filter-options.md) — operator semantics for the criteria you build into filters
* [Creating Templates](/templates/creating-templates.md) — reusable message content that can carry Special Attributes
* [Sending a Test](/campaigns/sending-a-test.md) — previewing as a specific contact
* [SMS Campaign](/campaigns/creating-a-campaign/sms-campaign.md) — the Personalize picker in SMS
* [Email Campaign](/campaigns/creating-a-campaign/email-campaign.md) — merge tags and Managed links in the email builder
* [Billing](/settings/billing.md) — plan limits and SMS overage, which message length feeds into


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://help.gleantap.com/campaigns/dynamic-content-with-special-attributes.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
