> This page is part of the [Customer.io documentation](https://docs-customerio.netlify.app). For the complete index, see [llms.txt](https://docs-customerio.netlify.app/llms.txt).
> Last updated: April 30, 2026

# Objects and relationships in campaigns

You can trigger campaigns based on changes to objects and relationships. You can target trigger data in messages and specify who should enter a campaign based on the relationship they have to objects.

## Trigger campaigns based on objects or relationships[](#trigger-campaigns-based-on-objects-or-relationships)

You can trigger campaigns based on changes to **objects** or **relationships**. You can trigger a campaign when:

*   an object is updated (like an Account’s name was changed).
*   a relationship between an object and person is added.
*   a relationship is changed (like a person is no longer associated with an Account).

[![The new campaign trigger selection page where Companies, one of the object types in the workspace, is selected. There are three trigger options: Company updated, Person added, and Relationship changed.](https://docs.customer.io/images/campaign-triggers-object-selected-1.png)](#8397d0fd9fbbf4766e5de4c63adf1342-lightbox)

You can also narrow in on the **audience** for these campaigns. For both object and relationship-triggered campaigns, you can choose to send to:

*   every person in the object or
*   certain people in the object

[![object-video-saas-trigger-1.png](https://docs.customer.io/images/object-video-saas-trigger-1.png)](#a4b3874e359f05dad926a3f7790146ad-lightbox)

For relationship-triggered campaigns, you can also choose to send only to the person that triggered the campaign.

 An object or relationship can’t fan out to more than 1,000 people.

If an update triggers journeys for more than 1,000 related people, none of them start a journey. You’ll see “Failed Journeys for Object/Relationship Campaign” in your activity log. This limit is per trigger event, not per campaign—your campaign can have more than 1,000 total recipients as long as each individual trigger doesn’t fan out to more than 1,000 people.

Learn more about [the fan-out limit](/journeys/object-and-relationship-campaigns/#audiences-over-1000).

Visit *Campaign Triggers* for more on [object-triggered campaigns](/journeys/campaign-triggers/#object-trigger) or [relationship-triggered campaigns](/journeys/campaign-triggers/#relationship-trigger).

### Per-trigger fan-out limit of 1,000[](#audiences-over-1000)

When an object or relationship changes, the campaign runs for every person related to that object. A single trigger event can’t fan out to more than 1,000 people. If a trigger includes more than 1,000 people, none of them start a journey.

This limit is **per trigger event**, not per campaign. Your campaign can have far more than 1,000 total recipients—the limit only applies to how many people a *single* object or relationship update can reach at once.

 Under the limit

#### Under the limit[](#Under the limit)

You have 10,000 company objects, each related to 5 people (50,000 people total). When any company’s properties change, the campaign triggers for the 5 people related to that company. Every person can go through the campaign because each trigger event fans out to only 5 people.

 Over the limit

#### Over the limit[](#Over the limit)

You run an auction site with a single auction object related to 50,000 interested people. When the auction’s properties change, the trigger tries to fan out to all 50,000 people at once—but the 1,000-person limit blocks the entire batch, and nobody starts a journey.

#### Why the limit exists[](#why-the-limit-exists)

A single object update can trigger messages for every related person simultaneously. Without a cap, one property change on a popular object could kick off thousands of simultaneous journeys, slowing down your workspace. The 1,000-person limit is a backstop to prevent this kind of problem.

#### Working within the limit[](#working-within-the-limit)

If an object or relationship update would fan out to more than 1,000 people, you might want to:

*   **Narrow your audience.** Switch from “Every person in the object” to “Certain people in the object” and add conditions to reduce the total number of people per trigger.
*   **Restructure your objects.** Break large objects into smaller ones with fewer relationships. For example, split a single “auction” object into regional auction objects so each update affects fewer people.

### Performance considerations[](#performance-considerations)

Imagine you have a few Account objects with 10 people related to each of them. Each Account has a `lifetime_value` attribute, and you have five segments and five campaigns that send messages based on an Account’s `lifetime_value`. Each time an Account’s `lifetime_value` gets updated, our system checks each of the 10 people related to that account to see if they should still belong to any of the segments or campaigns.

One little change - to a single Account’s attribute, in this case - caused us to check 100 things (5 segments x 10 people, 5 campaigns x 10 people). At this scale, that’s no problem.

But imagine you have hundreds of thousands of Accounts and most of them change every day. That can pretty quickly become hundreds of millions, even billions, of things for us to process. We know how to handle this - it’s our job! But if you ever get to an extreme enough scale, we’ll send you warning messages so you know well in advance if your account could be impacted. In very extreme situations, we might need to throttle the data we process from you - but again, we’ll always warn you long before we get to that.

Bottom line, the more segments and campaigns you have based on objects, the more you should make sure you’re targeting and updating the correct objects and relationships. For instance, instead of sending us your entire database every hour, send us only the object data we need. Of course, if you have any concerns, [reach out to us](mailto:product@customer.io) and we’ll be happy to help!

## Workflow actions for objects and relationships[](#workflow-actions)

You can use [object or relationship data](/journeys/objects-in-liquid/#object-liquid-in-workflow-actions) in any workflow item, including [*Create or update person*](/journeys/create-update-person/), [*Send event*](/journeys/event-action/), [*Send and receive data*](/journeys/webhooks-action/), [*Wait Until* blocks](/journeys/wait-until/#object-and-relationship-conditions), and [*Batch update*](/journeys/batch-update/).

How else would you like to manipulate object and relationship data in your campaigns? Let us know at [product@customer.io](mailto:product@customer.io). We’d love to hear your use cases!

### Random Cohort Branch[](#random-cohort-branch)

While [random cohorts](/journeys/random-cohort/) typically send people down different paths, you can use the **Cohort by** setting to send people related to the same [custom objectAn object is a non-person entity that you can associate with one or more people—like a company, account, or online course.](/journeys/objects/) down the same path. This ensures that people related to the same object all have the same campaign experience.

[![A random cohort branch with the Cohort By setting circled](https://docs.customer.io/images/random-cohort-by-setting.png)](#34c51fb55d915bcab218178b82208dff-lightbox)

### True/false branch[](#truefalse-branch)

In [true/false branches](/journeys/true-false), you can send people down different paths based on the their relationships to objects.

**All campaigns, except those with webhook triggers**

Drag a true/false branch onto your workflow. Click the branch, then click **Add condition > Relationship** to define a branch based on relationships to objects in your workspace. For instance, you could trigger a campaign when people open a page explaining a certain feature ([event-triggered](/journeys/campaign-triggers/#event-trigger) campaigns). Then you could branch them based on whether they’re related to any premium account to personalize messaging.

[![branch-true-false-relationship-condition-any-campaign.png](https://docs.customer.io/images/branch-true-false-relationship-condition-any-campaign.png)](#600a9f8c4c5796530958ca189a7f2033-lightbox)

You can add other conditions to refine the path further - conditions are only joined by AND statements, not OR.

**Object or relationship-triggered campaigns**

In object or relationship-triggered campaigns, you can also refine true/false branches by the trigger object. Drag a true/false branch onto your workflow. Click the branch then click **Add condition > Object-type-name (Trigger)** to define a branch based on the object triggering the campaign.

For instance, imagine you trigger an onboarding campaign when a [person is added](/journeys/campaign-triggers/#relationship-trigger) as an admin to any account. The onboarding flow for accounts on legacy plans is different from those on newer plans. So you add a true/false branch to your workflow and split users based on whether the account they were added to has a legacy plan type.

[![branch-true-false-object-condition-2.png](https://docs.customer.io/images/branch-true-false-object-condition-2.png)](#fdfcf249c176123bddc96f872c67ef83-lightbox)

Or maybe you trigger a campaign when an [account’s plan type is upgraded](/journeys/campaign-triggers/#object-trigger) to a modern one. This impacts admins of your accounts differently from all other roles so you add a true/false branch based on whether their relationship attribute `role` is equal to `admin`. For this, you’ll click **Add condition > Relationship**.

[![branch-true-false-relationship-condition-2.png](https://docs.customer.io/images/branch-true-false-relationship-condition-2.png)](#d00db29274edc8e6a44b875419c33233-lightbox)

### Multi-split branch[](#multi-split-branch)

You can send people down different paths based on object and relationship conditions in [multi-split branches](/journeys/multi-split). Unlike [true/false branches](#truefalse-branch), multi-split branches allow you to split people into more than two paths.

**All campaigns, except those with webhook triggers**

Drag a multi-split branch onto your workflow. Click the branch then click **Data Type > Relationship**. You can define people related to any object in your workspace.

For instance, imagine you want to encourage people to use your app after being inactive for 30 days. You could trigger a campaign when they join a segment based on inactivity then branch these users based on their plan type to personalize messaging.

[![A multi-split branch with whose condition is the current person is related to any account relationship attribute role...and there are three paths where role is equal to admin, editor, or reviewer.](https://docs.customer.io/images/branch-multi-split-segment-relationship.png)](#5c581878307dd5e4368c8ab3e5f5277e-lightbox)

**Object or relationship-triggered campaigns**

With object and relationship-campaigns, you can also refine branch conditions based on the trigger object. Drag a multi-split branch onto your workflow. Click the branch then click **Data Type > Object-type-name (Trigger)**.

For instance, imagine you trigger an onboarding campaign when a person is added as an admin to any account. The onboarding flow for accounts on legacy plans is different from those on newer plans. So you add a multi-split branch to your workflow and split users based on `plan_type`. You create different messaging for those on a `legacy` plan, `premium` plan, and all others.

[![This shows the sidebar for a multi-split branch based on an object attribute. At the top, the name of the branch is Plan type. Under that, the data type of Account is selected. Under that, the attribute plan_type is specified. Below that are the paths. Path 1 is set equal to the value legacy. Path 2 is set equal to the value premium.](https://docs.customer.io/images/branch-multi-split-sidebar-2.png)](#cf051a772077dbb727b2813ddf6621e9-lightbox)

Or maybe you trigger a campaign when an account’s plan type is upgraded to Enterprise. This impacts people differently based on their role on the account, so you add a multi-split branch based on the relationship attribute `role`. You create different messaging for admins, managers, and anyone without those roles. For this, you’ll click **Data Type > Relationship**.

[![This shows the sidebar for a multi-split branch based on a relationship attribute. At the top, the branch name is Role. Under that, the data type of Relationship is selected. Under that, the attribute is defined as: The current person is related to the triggering object where their relationship role. Below that, the paths are split based on the relationship attribute role. Path 1 is set equal to admin. Path 2 is set equal to manager.](https://docs.customer.io/images/branch-multi-split-sidebar-4.png)](#d398b60b5a7a0ee52423ea08d17e6aad-lightbox)

## Trigger a campaign with a relationship-based segment[](#segment-triggered-campaigns)

People enter segment-triggered campaigns when they join (or leave) a segment. But **when you create a relationship-based segment, a person only joins the segment for their FIRST relationship to an object matching your criteria.** Their segment membership won’t change on subsequent relationships. This means that a person will only trigger a campaign for the first relationship matching your segment criteria. To trigger a campaign for each relationship change, [create a relationship-triggered campaign](#trigger-campaigns-based-on-objects-or-relationships).

For example, imagine that you have a segment of people related to online classes, and you use that segment to trigger a campaign:

*   When a person signs up for their first online class, they’ll join the segment and enter the campaign.
*   When they sign up for another online class, they won’t trigger the campaign again because their segment membership didn’t change!

In this example, a person would only re-join the segment if they unenrolled from all their classes, causing them to leave the segment, and then re-enrolled in a class later.

**Exit Conditions** follow these same principles: a person won’t leave a segment (causing them to exit a campaign) until they’re no longer related to *any* objects matching your segment criteria.

### Use an object in a segment[](#use-an-object-in-a-segment)

You can create object-oriented [segmentsA group of people who match a series of conditions. People enter and exit the segment automatically when they match or stop matching conditions.](/journeys/data-driven-segments/) on the *Segments* page, or when you create campaigns and newsletters. [Learn more about how relationship-based segments work in campaigns](#segment-triggered-campaigns).

1.  Go to **Segments** and click **Create Segment**.
2.  Give your segment a *Name* and a *Description*, and click **Create Data-Driven Segment**.
3.  Under *Add condition or group*, select **Relationship** and set a condition to *Relationship to `your object type` exists*.
    
    [![set up a segment of people related to an object](https://docs.customer.io/images/object-segment.png)](#adfb261d7014c4bc38e97c5bfe40f0af-lightbox)
    
4.  (Optional) you can refine your selection by clicking *Refine* and selecting an object-based attribute condition. For example, you might want to limit a newsletter segment based on a `country` or `plan_name` attribute.
5.  When you’re done, click **Save Changes**.

Now you can use your segment in newsletters or to trigger campaigns.

### You cannot backfill relationships[](#you-cannot-backfill-relationships)

We don’t have a concept of historical relationships in Customer.io—at least not yet. For example, a person might have joined a *company* several years ago, but it will appear that they only recently joined the company when you set their relationship in Customer.io.

Because you can’t backfill relationships, you should be careful when using relationship-based segments to trigger your campaigns. For example, if you want to send a welcome campaign for new employees of a company, and you relate people to the company after you set up your campaign, you may inadvertently trigger a welcome campaign for those people.