Customer.io Can Now Trigger Off a Date on a Custom Object. Renewal Reminders Finally Live on the Account

By·Published·Updated
Customer.io Can Now Trigger Off a Date on a Custom Object. Renewal Reminders Finally Live on the Account

On 12 September 1960 the Ministry of Transport started testing cars. Ernest Marples brought it in on a voluntary basis, using powers in the Road Traffic Act 1956, and the first test checked the brakes, the lights and the steering. Only vehicles over ten years old had to bother.

The MOT now covers twenty different parts and systems, and most vehicles over three years old need one every year. What hasn't changed is what the test attaches to. The MOT belongs to the vehicle. Sell the car and the expiry date goes with it, because roadworthiness was never a fact about the driver... it was always a fact about the machine.

Your accounts work the same way. A renewal date is a fact about the account. So is a contract-end date, a trial-end date, a licence anniversary. Until 22 July 2026, Customer.io wouldn't read a date that way, and the workaround it forced on you quietly corrupted your data model. That changed with one release note. This post covers what shipped, the exact clicks, the gotchas the screenshots don't show, and when you should still reach for a different trigger.

The date was always on the account. Customer.io just refused to read it there.

Customer.io's Important date trigger fires an automation on a date held in an attribute. Until late July 2026 it could only read that attribute from one place, the person profile. If the date you cared about lived on an account, a subscription or a contract, the trigger couldn't see it.

That left one option. Copy the date onto every person attached to the account, and keep copying it.

What denormalising a date onto every profile actually did to your workspace

It created ten copies of one fact and no way to keep them honest.

Say an account has ten seats and renews on 3 November. To send a T-14 reminder you wrote renewal_date onto all ten profiles. Fine on day one. Then finance moved the renewal to 17 November after a mid-term upgrade, and you had to find and rewrite ten values. Then a new admin joined in October and nobody backfilled her profile, so she never got the reminder. Then someone left, kept a stale renewal_date, and got a renewal email for an account they no longer belonged to.

None of that is a Customer.io bug. It's what happens to any duplicated fact. Customer.io's own objects documentation names the problem plainly: "Without objects, you'd need to set attributes or send an event for every individual member of the account." Objects exist precisely so account facts sit on the account. The date trigger was the last place that rule didn't hold.

If you're new to the distinction between an object and a collection, the difference matters here. Collections are reference data and custom objects are entities with relationships, and only the latter can carry a renewal date that people relate to.

What shipped on 22 July 2026

The Important date trigger can now read a date attribute from a custom object type instead of a person profile. Customer.io's release note puts it this way:

You can now trigger an automation off a date attribute on a custom object. This means you can send messages relative to a date stored on an object, like trigger reminder campaigns based on reservations or membership renewals, and avoid storing duplicate data on people's profiles! To get started, choose the trigger type Important date and select the relevant object type. Narrow your audience further by adding Filters and Audience settings.

Read the last clause twice. "Avoid storing duplicate data on people's profiles" is Customer.io conceding that the old pattern was duplication, not design. The triggers documentation was updated the same day with a new section, "Dates unique to custom objects". Its worked example is the one B2B teams have been asking for: remind people to renew 14 days before their account expires.

Why the old workaround was a data-modelling anti-pattern

One fact should live in one place. A renewal date belongs to the contract, not to the person in billing, the ops lead, and the contractor with read-only access.

Denormalisation is a legitimate technique when you accept the cost knowingly and control the writes. Neither applied here. Most teams weren't choosing to denormalise, they were working around a trigger limitation, usually with a nightly sync that overwrote profile attributes from the CRM. That sync becomes load-bearing infrastructure for a marketing reminder, and when it fails at 3am nobody notices until a renewal goes out for the wrong date.

The account-level case is worth reading in full if you're rebuilding this: our guide to custom objects for B2B and multi-seat SaaS covers the modelling decisions that sit underneath the trigger.

How to set it up

The flow is the one you already know from birthday and anniversary campaigns. Only the second step is new.

Choose Important date, then Date from > Object type

Pick Important date as the trigger type. Under Date from, you now choose between Profiles and your Object types. Select the object type that holds the date, then pick the Date attribute on it. Customer.io's own screenshot shows the object type set to Accounts and the date attribute set to renewal_date.

If you've been storing campaign state on profiles because there was nowhere better to put it, this is the same instinct that journey attributes fixed for in-flight campaign data. Facts about a thing belong on the thing.

On, before or after the date, by a set number of days

The date settings offer three options. On the date fires on the date itself. Before the date triggers "a set number of days before the date attribute", and After the date does the reverse.

Before the date is the renewal workhorse. A T-30, T-14 and T-7 sequence is three automations pointed at the same object attribute with different day offsets, which is easier to reason about than one campaign with branching waits.

Once, Monthly or Yearly

Recurrence controls how often someone can enter. Once means a person triggers the automation one time. Monthly repeats on the same day number each month. The docs cover the awkward case too: if the current month doesn't include that day, like the 31st, the automation fires on the last day of the month instead. Yearly repeats on the same month and day, so a date attribute of 5 June 2026 triggers again on 5 June 2027.

For an annual contract, Yearly plus Before the date gives you a renewal reminder that keeps working without anyone touching it again.

Filters decide which accounts. Audience decides which people.

These two settings do different jobs and it's worth being precise about which.

Filters narrow the objects. Click the trigger block, select Filters, and add object attributes as conditions, so only accounts with a status of active enter. Audience narrows the people. Select Audience and choose whether every profile related to those objects enters, or only certain ones.

That second setting is the whole point of the feature. One renewal date on one account object, and you decide it goes to admins and billing contacts rather than all forty seats.

The gotchas nobody screenshots

None of these appear in the release note, and each one has cost somebody a send.

The timezone still comes from the person, not the object

The object does not carry a send timezone. You pick a time of day for the automation. The docs are explicit about the alternative: "if you store your audience's timezone as an attribute, you can select the user's time zone to trigger your automation."

So the date comes from the account and the send time comes from the person. For a multinational account with people in London, Austin and Singapore, a single renewal date produces three different send moments. That's usually what you want. It also means an account with no timezone attribute on its people falls back to the single time you picked on the trigger, which is a real limitation rather than a rounding error.

It fires on the date, not the time stored in the attribute

Customer.io schedules the automation on the date, not the time of the attribute. The docs say so twice, once in each flow: "Your workspace schedules your automation based on the date, not the time of this attribute. You set the time in a later step."

If your renewal_date is stored as 2026-11-03T09:00:00Z and you assume the reminder goes at 9am, it won't. It goes at whatever time you set in the time-of-day step. Appointment reminders are where this hurts most, because the time in the attribute is the thing the reminder is about.

Unix or ISO 8601, or it never fires

Automations trigger on a Unix timestamp or an ISO 8601 value. The supported ISO formats run from YYYY-MM (which defaults to the first of the month) through YYYY-MM-DD, YYYY-MM-DDThh:mm:ssZ and YYYYMMDDThh:mm:ssZ to fractional-second and UTC-offset forms. The FAQ below lists them all.

Anything else fails silently. In Customer.io's words: "If a profile doesn't have this attribute, or the attribute isn't in the right format, they'll never trigger the automation." A date sent as 03/11/2026 from a spreadsheet import will sit on the object looking correct and never fire. Check the attribute type before you build the campaign, not after the first renewal cycle goes quiet.

Nested dates do work. You can point the trigger at appointments.next_date inside a JSON object, or appointment_times[0] for the first timestamp in an array. One trade-off comes with it: your workflow can't show the number of profiles that will receive a message when you use a nested attribute.

Exit conditions can't read the object directly

This is the one that catches people. You cannot set an exit condition on an object attribute.

Customer.io's exit conditions offer three condition types: profile attributes, events and segments. There's no fourth option for object attributes. So "make renewed accounts stop receiving the T-7 reminder" needs one more hop than you'd expect.

The documented route is a segment. On the objects and relationships in automations page, you create a data-driven segment, add a Relationship condition set to "Relationship to your object type exists", then click Refine and add an object-based attribute condition. Build a segment of people related to an account whose status is renewed, then exit on that segment. It works, it's just two steps rather than one. Worth folding into a wider exit conditions audit rather than treating as a one-off.

One more from the same page, easy to miss during a migration: "You cannot backfill relationships. This means that a profile might appear to join a company recently when, in reality, they might have joined several years ago. This can lead to unintended triggers for automations."

What about the 1,000-profile limit?

It doesn't apply to this trigger, at least not as documented. The ceiling that says "an object or relationship can't fan out to more than 1,000 profiles" appears on the triggers page inside the Object change and Relationship sections, not in the Important date sections. If you also run object-updated automations, know that the limit is per trigger event rather than per automation, and that exceeding it means none of the related profiles start a journey. Don't assume it governs your date trigger, and don't assume it doesn't. Test with a large account before you rely on it.

Five account-level reminders worth building now

Renewal reminders are the obvious one, and the stakes are real. Recurly's 2026 State of Subscriptions report finds annual plans "delivering 50–60% higher revenue per user despite higher renewal risks". The renewal moment carries more revenue and more risk at once, so it's worth automating properly.

Renewal at T-30, T-14 and T-7. Three automations, one renewal_date on the account object, audience set to admins and billing contacts. The docs' own example is 14 days before an account expires.

Contract-end reminders for the people who can act. A contract_end_date on a contract object, audience narrowed by relationship role, so procurement hears about it and end users don't.

Trial end on the account, not the user. In a multi-seat trial the trial belongs to the workspace. Put trial_ends_at on the account and message whoever you choose, instead of racing to copy the date onto each new invitee.

Seat and licence anniversaries. Yearly recurrence plus On the date gives you an account anniversary message that never needs rebuilding.

Reservations and appointments. Customer.io names reservations directly in the release note. The booking is the object, the attendees are the audience.

There's a dunning-shaped hole next to all of this. Churnkey's State of Retention 2025 reports that "involuntary churn can easily comprise 40% of your churn, if not more, depending on the nature of your business". Looking at dunning email and SMS campaigns alone, the report found the "average recovery rate was 42%". Recurly puts a number on the recovered side: "In 2025 alone, the Software industry reclaimed over $155 million in revenue through recovery tools." A renewal reminder that lands before the card is charged heads off some of those failures before they become recovery work. If the charge has already failed, that's a different flow, and our Customer.io dunning email flow covers it.

When not to use it

Use Important date only when the trigger is genuinely a date. If the trigger is a behaviour or a state change, reach for something else.

A payment failing is an event. A plan downgrading is an object update. A seat being added is a relationship change. All three have their own trigger types. Forcing them through a date attribute means writing a date you then have to maintain, which puts you back in the duplication problem this feature just solved.

This isn't a licence to rebuild calendar-driven blasts either. We've argued before that time-based drips are dead, and that still holds. A drip that sends on day 3 because day 3 arrived is lazy. A reminder that sends 14 days before a contract expires is anchored to something real in the customer's world. The date trigger is the right tool for the second and the wrong tool for the first.

Frequently asked questions

Can Customer.io trigger a campaign from a date stored on a custom object?

Yes, as of 22 July 2026. The Important date trigger can read a date attribute from a custom object type rather than a person profile. Under Date from on the trigger step, choose an object type instead of Profiles, then select the date attribute held on that object.

Which trigger type do I use for a renewal date held on an account object?

Important date. Choose it as the trigger type, set Date from to your Accounts object type, and pick the date attribute, such as renewal_date. Object updated and Relationship triggers fire on changes rather than dates, so they're the wrong tool for a scheduled renewal reminder.

Can it send the reminder a set number of days before the renewal or contract-end date?

Yes. The date settings include Before the date, which triggers the automation a set number of days before the date attribute, along with On the date and After the date. A T-30, T-14 and T-7 sequence is three automations reading the same object attribute with different offsets.

Who receives the message when the date lives on the account object?

You decide, using the Audience setting on the trigger. Select Audience and choose whether every profile related to those objects enters the automation, or only certain profiles. Customer.io's example narrows the audience to people whose role on the account is admin.

What date formats does Customer.io accept for the trigger?

Unix timestamps or ISO 8601 values. Supported ISO forms include YYYY-MM (which defaults to the first of the month), YYYY-MM-DD, YYYY-MM-DDThh:mm:ssZ, YYYYMMDDThh:mm:ssZ, YYYY-MM-DDThh:mm:ss.ms and formats carrying a UTC offset. Anything else means the automation never fires for that record.

Does it use the account's timezone to decide send time?

No. The object doesn't carry a send timezone. You pick a time of day on the trigger, and if you store your audience's timezone as a profile attribute you can select the user's time zone instead. The date comes from the object, the send time comes from the person.

Do I still need to copy the renewal date onto every person's profile?

No, and you should stop. That was the workaround the old trigger forced, and Customer.io's release note frames the fix as a way to "avoid storing duplicate data on people's profiles". Keep the date on the object, delete the copies, and make sure whatever sync was writing them is turned off before it overwrites something else.

Can I make the reminder recur every year or month from an object date?

Yes. Recurrence offers Once, Monthly and Yearly. Yearly repeats on the same month and day, so a date attribute of 5 June 2026 triggers again on 5 June 2027. Monthly repeats on the same day number, and where a month doesn't contain that day, like the 31st, the automation fires on the last day of the month.

Can I trigger off a date nested inside a JSON object or array on the object?

Yes. You can specify a timestamp attribute inside an array or object, using notation such as appointments.next_date for a timestamp within a JSON object or appointment_times[0] for the first timestamp in an array. One trade-off applies: your workflow can't show the number of profiles that will receive a message when you use a nested attribute.

How do I stop reminders once the account has renewed?

Through a segment, not a direct object condition. Exit conditions offer profile attributes, events and segments only. Build a data-driven segment with a Relationship condition to your object type, refine it with an object-based attribute condition such as status equals renewed, then exit on that segment.

What happens if the date attribute is missing or in the wrong format?

Nothing happens. Customer.io states that if a profile doesn't have the attribute, or the attribute isn't in the right format, they'll never trigger the automation. The record simply never enters, so validate the attribute on a handful of objects before you activate the campaign rather than waiting to notice an absence.

Does the 1,000-profile fan-out limit apply to this trigger?

The documented limit sits on Object change and Relationship triggers, not on the Important date trigger. For those triggers, an object or relationship can't fan out to more than 1,000 profiles. The limit counts per trigger event rather than per automation, and going over it means none of the related profiles start a journey. Test a large account before assuming your date trigger behaves differently.

Can I limit the trigger to certain accounts only?

Yes, with Filters. Click the trigger block, select Filters, and add one or more object attributes as conditions, so only accounts matching them enter the automation. Filters narrow which objects qualify; Audience narrows which related people receive the message.

Should I use this instead of an Object updated trigger?

Use Important date when the trigger is a date and Object updated when the trigger is a change. A renewal falling due in 14 days is a date. A plan changing to premium, a status flipping to churned or a seat count increasing are updates, and forcing them through a date attribute recreates the duplication this feature removed.

Does modelling accounts as objects cost more?

Objects count towards your profile total. Customer.io's billing documentation states that "[p]eople and custom objects both have their own profiles, but we bill based on the total number of profiles in your account. People and objects count together toward your plan's profile limit." Both draw down the same allowance. Ten thousand accounts modelled as objects is ten thousand profiles, so size it before you import.


Modelling account facts properly is the difference between a renewal programme that survives a data change and one that quietly rots. If you'd rather have someone rebuild yours on the object model instead of the profile copies, get in touch or take a look at how we run Customer.io as an agency.

Sources

Want this working in your Customer.io workspace?

It's what we do all day for SMBs—strategy, automations, deliverability and hands-on execution.

See how we work as a Customer.io agency →
David Crowther
Book a free consultation →

On our call, you'll be speaking with David Crowther, founder of NerveCentral.

Our initial consultation is not a sales call—you'll talk, I'll listen and ask questions—then I'll come back to you within 48 hours with our best ideas on how to grow your business.