Nightly HubSpot to OneSignal push audience tag sync
Every night we copy the customer details that matter onto your push audience, so campaign targeting always matches your CRM instead of stale tags.
Every night at 2am, keep my OneSignal audience in sync with HubSpot so the marketing team can target push campaigns using current CRM data instead of stale tags. Use a cron trigger. Every step is a fixed field to field mapping over structured records with no judgement calls, so build this as a code workflow.
Start by pulling contacts from HubSpot with the List Contacts operation. Request only the properties that matter for targeting: lifecycle stage, plan or tier, contact owner, last activity date, and the property that stores the person's OneSignal external user id. List Contacts is paginated, so page through every result and keep going until HubSpot stops returning a next page cursor. Do not assume the whole audience fits in one page.
For every contact that carries an external user id, write those values onto the matching OneSignal user with the Edit Tags by External User ID operation. Each HubSpot property maps one to one onto a named OneSignal tag: lifecycle stage to lifecycle_stage, plan or tier to plan, contact owner to owner, and last activity date to last_activity_date. Keep the tag names stable and predictable, because the marketing team's segments are built on top of them.
Two rules drive correctness. First, skip any contact with no external user id, since there is no OneSignal user to write to, and count it as skipped. Second, when a HubSpot property is blank, still send the matching tag with an empty string rather than omitting it. On this operation an empty string deletes the tag, and that is what makes the clean up half of this sync work: someone who drops out of a plan or goes quiet stops matching that segment on the very next run, so nobody is left sitting in a segment they no longer belong to.
Pace the writes, because a nightly full sync over a large contact list will otherwise trip OneSignal's limits. User and subscription writes are capped at 1,000 per second per app, and separately at 1 request per second for any individual user or subscription, so batch the updates and spread them out instead of firing the entire contact list at once. If OneSignal returns a 429, read the Retry-After header, wait that many seconds, then retry with exponential backoff. Treat 400, 401 and 403 as permanent failures for that contact: do not retry them, record the contact as errored, and continue, so one bad record never halts the run.
Finish by posting a one line summary to Slack with the Send a Message operation, reporting how many users were updated, how many were skipped for having no external user id, and how many errored. Send it to the marketing operations channel.
Example output
What does this prompt do?
- Runs on its own every night and reads your current contact list, so nobody has to maintain push audience tags by hand.
- Copies the details your marketing team actually targets on, such as lifecycle stage, plan or tier, contact owner, and last activity date, onto each matching person in your push tool.
- Clears a tag when the matching CRM field is empty, so people drop out of segments like trial users or dormant accounts as soon as they no longer belong there.
- Posts a one line recap to your team channel each morning showing how many people were updated, skipped, or hit a problem.
What do I need to use this?
- A HubSpot account containing the contacts you want to target
- A OneSignal app, plus the customer ID you already store on each contact so the two systems can be matched up
- A Slack workspace and a channel where the nightly recap should land
- Contact records filled in with the details you want to target on, for example lifecycle stage or plan
How can I customize it?
- Change the 2am timing, or run the sync more than once a day if your CRM changes quickly
- Pick exactly which contact details become targeting tags, and what each one is called in your push tool
- Choose the channel that receives the recap, or narrow the sync to a single list of contacts instead of everyone
FAQs
What happens to contacts who are not in my push tool yet?
Will this send anyone a push notification?
Do I have to rebuild my existing segments?
What happens when someone changes plan or goes quiet?
Will this work with a large contact list?
Related templates
When your flight moves, your calendar times get corrected automatically and you get a Slack note naming the meetings you're about to miss.
Every 15 minutes, forwarded phishing reports get traced back to the server that really sent them, with a verdict in Slack and the worst senders reported.
Twice every weekday, the conversations from your social inbox land on the right HubSpot contact timelines, with a Slack recap for sales.
Every weekday at 7am, sign in to the tender portals you track, filter new notices against your bid criteria, and open a deal for the ones worth chasing.
Every morning, find the addresses that hard bounced or filed a spam complaint, update the matching HubSpot contacts, and post a short Slack recap.
When a HubSpot deal hits Closed Won, the customer's plan, seats and renewal dates land in your DynamoDB accounts table, with a Slack note showing what changed.
Stop targeting push campaigns with stale tags.
Let your CRM drive who hears from you, refreshed automatically every night while your team sleeps.