Nightly sync of HubSpot list to Meta Ads Custom Audience

Every night at 2am, rebuild a Meta Ads Custom Audience from a HubSpot list so retargeting always matches your current CRM segment.

Deterministic Code
HubSpotMeta AdsSlack BotMarketingData SyncNotifications & Alerts
PromptCreate

Build a code workflow that runs every night at 2am and keeps a Meta Ads Custom Audience in sync with a HubSpot contact list, so retargeting always reflects the current CRM segment. This is a deterministic pipeline, not a decision agent.

Trigger: cron, daily at 02:00 in the workspace's default timezone.

Inputs (so this same workflow can be reused for multiple segments like churn risk, high LTV, product A buyers):

1) HubSpot list identifier (the named list or filter to pull from).

2) Meta Ads Custom Audience id (a pre-created customer list audience).

3) Slack channel id for the summary message.

Steps:

1. Use HubSpot Search Contacts to pull every contact that matches the given list or filter. Paginate all the way through until the full membership is loaded. Request email, phone, first name, last name, city, state, country, and zip so Meta has plenty of match fields.

2. Format each contact into the user record shape Meta's Custom Audience upload expects. Normalize email (trim and lowercase) and phone (digits only, keep country code) so the platform's hashing produces stable matches. Skip contacts with no email and no phone.

3. Call the Meta Ads Replace Users in Custom Audience operation against the given audience id. This swaps the entire membership in a single session, so adds and removals both take effect atomically. Handle Meta rate limit responses with retry-and-backoff, and fail loudly on non-retryable errors.

4. Send a Slack Bot Send a Message to the configured channel with a short summary: HubSpot list name, Meta audience id, records pulled from HubSpot, records sent to Meta, session id, records Meta accepted for matching, and any error codes returned. Keep it terse enough to be readable in a channel.

Error handling: strict. If HubSpot pagination fails, abort before touching Meta so we never send a partial list. If Meta rejects the session, post the failure to Slack with the error payload so someone can act on it in the morning.

Additional information

What does this prompt do?
  • Pulls every contact from a chosen HubSpot list, no matter how large.
  • Rebuilds a matching Meta Ads Custom Audience from scratch each night, so adds and removals are reflected in a single atomic swap.
  • Posts a short Slack summary showing how many contacts were sent, how many Meta accepted for matching, and any errors from the upload.
  • Runs unattended on a schedule, so retargeting audiences stay fresh without anyone touching a CSV.
What do I need to use this?
  • A HubSpot login with access to the list you want to sync.
  • A Meta Ads account and a Custom Audience already created for customer lists.
  • A Slack workspace where the summary should be posted.
  • The HubSpot list identifier and the Meta Custom Audience identifier ready to paste in as inputs.
How can I customize it?
  • Change the time of day or the run frequency, for example run it hourly for a fast-moving segment.
  • Point it at a different HubSpot list and Meta audience to sync a second segment such as churn risk or high value buyers.
  • Change the Slack channel or replace it with an email summary if the marketing team lives somewhere else.

Frequently asked questions

Do I need to hash emails and phone numbers myself?
No. The workflow prepares each contact's email and phone in the exact shape Meta expects and Meta handles the matching. You just point it at the HubSpot list and the Custom Audience.
What happens if someone was removed from the HubSpot list?
Because the workflow replaces the whole audience each night, anyone no longer on the HubSpot list is also removed from the Meta audience automatically. Adds and removals happen together in one swap.
Can I use this for more than one audience?
Yes. The HubSpot list and the Meta audience are inputs, so you can run separate copies for different segments like product buyers, high value customers, or churn risk.
Will this work with a very large list?
Yes. The workflow pages through the full list until every matching contact has been pulled, then sends them to Meta in one session.
What if Meta rejects the upload or throttles the request?
The workflow watches for Meta rate limit and error responses, retries where it can, and includes any final error codes in the Slack summary so you know exactly what to fix.

Stop uploading retargeting CSVs by hand.

Connect HubSpot, Meta Ads, and Slack once, and Geni keeps your Custom Audience in lockstep with your CRM every night at 2am.