The problem
Our customer.io workspace only has user_id
enabled as an identifier for contacts. This is typically fine, except for when collecting email leads for people who may or may not have an account (and therefore a user_id
).
When someone provides us with their email through a lead capture form, we need to send them a campaign until they create an account. At that point, they need to switch over to receiving our onboarding campaign instead.
However, because they receive a different user_id
when they create an account, there’s not a native way in customer.io to attribute their conversion / early exit criteria to the first campaign (without enabling email identifier globally for the workspace).
The workaround
We set up a campaign that fires every time someone creates a new account. It uses a webhook to query our workspace’s API to check if there’s a duplicate email address that we acquired through a lead capture form. If it finds one, it makes another webhook call to merge those profiles together.
Here’s what that looks like:
![](https://uploads-us-west-2.insided.com/customerio-en/attachment/b9da7b90-67f6-4159-a412-4b3952b39fa2.png)
Step by step breakdown
1. Check if dupe email from lead capture form exists
In the first POST request, we check:
- If any other contacts in our workspace have an email address that matches the address of the person who created an account
- And whether that duplicate has the attribute
source
. We only assign this attribute to contacts collected from an email lead capture form and don’t want to merge any other duplicates with this campaign (though you could if you wanted to).
Endpoint: https://api.customer.io/v1/customers
{
"filter": {
"and": "
{
"attribute": {
"field": "email",
"operator": "eq",
"value": "{{customer.email}}"
}
},
{
"attribute": {
"field": "source",
"operator": "exists"
}
}
]
}
}
In the “response” tab of the webook, we set a temporary attribute duplicate_profile
equal to the user_id
of the duplicate contact.
API doc on searching for customers
2. Check if profiles need merging
Using a true/false branch, we check if the person who created an account has the duplicate_profile
attribute. If they don’t, they simply exit the campaign without any changes made to them.
If they do have that attribute, they continue on to the next step.
3. Merge duplicates
Here we make another webhook request to merge the duplicates:
Endpoint: https://track.customer.io/api/v1/merge_customers
{
"primary": {
"id": "{{customer.id}}"
},
"secondary": {
"id": "{{customer.duplicate_profile}}"
}
}
The person who just created an OpenPhone account is the primary, and we merge them with the secondary (duplicate) profile created when we first captured their email address. They inherit the email and activity history of the secondary profile and continue any campaign journeys the secondary is already on.
4. Remove duplicate_profile
attribute
Lastly, we use the “create or update person” workflow action to remove the duplicate_profile
attribute to keep things tidy, since it’s no longer needed.