Identity Resolution Guide
Identity Resolution Guide
A comprehensive guide to understanding and using identity resolution when integrating with our contact management platform.
Overview
Identity resolution is the process of matching incoming contact data against your existing contacts. It determines whether to create a new contact or update an existing one based on identifiers or IDs like email addresses, phone numbers, customer IDs, and other unique identifiers or IDs
Why Identity Resolution Matters
When integrating with our platform, you'll encounter situations where:
- The same person interacts through multiple channels (email, phone, web, app)
- Users provide different identifiers at different times (email first, phone later)
- External systems have different IDs for the same person
- You need to progressively build a complete customer profile over time
Without proper identity resolution, you end up with:
- ❌ Duplicate contact records for the same person
- ❌ Fragmented customer profiles across systems
- ❌ Incomplete view of customer interactions
- ❌ Poor user experience (multiple accounts, repeated onboarding)
With identity resolution, you achieve:
- ✅ Single, unified contact record per person
- ✅ Progressive enrichment as you learn more about each contact
- ✅ Accurate customer analytics and reporting
- ✅ Seamless experience across all touchpoints
Core Concepts
What is a Contact?
A contact represents a unique person profile in your workspace. Each contact:
- Has a unique system generated ID i.e. Contact ID
- Belongs to a workspace only
- Contains attributes (name, address, custom fields)
- Has events based on a timeline (opened email, viewed page)
- Has associated objects (companies, custom objects)
- Is associated with one or more identifiers e.g. email, phone number or external customer ID
What is an Identifier?
An identifier is a key-value pair that uniquely identifies a contact:
Esempio di codice
{
"key": "emailaddress",
"value": "jane@example.com"
}
Common identifier types:
- emailaddress: Email addresses
- phonenumber: Phone numbers
- customer_id: Your external system's customer ID
- user_id: Application user ID
- account_id: Account number
- Custom keys specific to your business
Key principle: Each identifier value can only belong to ONE contact at a time. This ensures uniqueness across your contact database.
Resolution vs Aliasing
When sending contact data to our platform, you work with two types of identifiers:
1. Resolution Identifiers
Purpose: Update existing or create a contact
These identifiers participate in your chosen identity resolution strategy and determine which contact record to work with.
Esempio di codice
{
"identifiers": [
{"key": "customer_id", "value": "CUST_12345"}
]
}
2. Alias Identifiers
Purpose: Add supplementary identifiers to an already-found contact
These are added on a best-effort basis after the contact is found. If an alias is already taken by another contact, it's simply skipped (not an error).
Esempio di codice
{
"aliasIdentifiers": [
{"key": "emailaddress", "value": "customer@example.com"},
{"key": "phonenumber", "value": "+12345678900"}
]
}
Identity Resolution Strategies
Choose the strategy that matches your data quality and business requirements.
Strategy 1: Strict Resolution
When to use:
- ✅ You have high-quality data with strong guarantees
- ✅ You want to catch data inconsistencies immediately
- ✅ You need strict control over identifier associations
- ✅ Data errors should be surfaced, not hidden
Behavior: All provided identifiers must match a single contact. If they match different contacts, the operation fails with an error.
Example scenario:
Imagine you're integrating a CRM system where each customer has both an email and phone number that should always be together:
Existing data in Bird:
Contact A: email = alice@company.com
Contact B: phone = +11234567890
Your integration sends the following to Bird:
Esempio di codice
{
"strategy": "strict",
"identifiers": [
{"key": "emailaddress", "value": "alice@company.com"},
{"key": "phonenumber", "value": "+11234567890"}
],
"attributes": {
"firstName": "Alice",
"company": "Acme Corp"
}
}
Result: ❌ ERROR - identifiers match different contacts
Action needed: Investigate why email and phone are on separate contacts in Bird
Use cases:
- Financial systems with strict data integrity requirements
- Healthcare systems requiring accurate patient matching
- Compliance-sensitive operations
- Data quality validation and auditing
Strategy 2: First Alias Resolution
When to use:
- ✅ You collect identifiers progressively over time
- ✅ You want flexibility in adding new identifiers
- ✅ You're okay with identifiers staying separate if they conflict
- ✅ You prefer successful operations over strict validation
Behavior: Uses the first available identifier to find the contact, then tries to add remaining identifiers. If an identifier is already on another contact, it's skipped (not an error).
Example scenario:
Your e-commerce site collects customer data across multiple sessions:
Session 1: User provides email during newsletter signup
Esempio di codice
{
"strategy": "first_alias",
"identifiers": [
{"key": "emailaddress", "value": "shopper@email.com"}
],
"attributes": {
"source": "newsletter_signup",
"interests": ["electronics"]
}
}
Bird creates Contact A with email
Session 2: Same user makes purchase, provides phone
Esempio di codice
{
"strategy": "first_alias",
"identifiers": [
{"key": "emailaddress", "value": "shopper@email.com"},
{"key": "phonenumber", "value": "+19876543210"}
],
"attributes": {
"lastPurchase": "2025-10-22",
"totalSpent": 299.99
}
}
Bird finds Contact A via email, adds phone number
Contact A now has both email and phone
Session 3: User provides loyalty card at physical store
Esempio di codice
{
"strategy": "first_alias",
"identifiers": [
{"key": "emailaddress", "value": "shopper@email.com"},
{"key": "loyalty_card", "value": "LOYAL_789456"}
],
"attributes": {
"inStoreVisit": true,
"preferredStore": "Downtown Location"
}
}
Bird finds Contact A via email, adds loyalty card
Contact is progressively enriched across touchpoints
Use cases:
- Multi-channel customer engagement platforms
- Progressive web app user tracking
- SaaS applications with gradual user onboarding
- Marketing automation platforms
Strategy 3: First Resolution
When to use:
- ✅ You only need to find the contact, not add identifiers
- ✅ You're updating attributes without changing identifiers
- ✅ You want minimal impact on existing identifier associations
- ✅ Read-mostly operations
Behavior: Uses the first available identifier to find the contact. Additional identifiers in the request are ignored.
Example scenario:
Your analytics system updates contact attributes based on user behavior:
You track user activity and want to update their profile
Esempio di codice
{
"strategy": "first",
"identifiers": [
{"key": "user_id", "value": "USER_12345"},
{"key": "session_id", "value": "sess_abc123"} // Ignored
],
"attributes": {
"lastActive": "2025-10-22T14:30:00Z",
"pageViews": 47,
"featureUsage": {
"dashboard": 15,
"reports": 8,
"settings": 2
}
}
}
Bird finds contact by user_id
Bird Updates attributes only
session_id is NOT added to the contact
Use cases:
- Activity tracking and analytics
- Attribute-only updates
- Event processing systems
- Webhook handlers that shouldn't modify identifiers
Alias Identifiers
The Challenge
Imagine this scenario:
- You're integrating an external CRM system
- Customers provide different identifiers through different touchpoints
- Sometimes an email or phone is already associated with another contact
- You don't want the entire operation to fail because of one conflict
The Solution: Alias Identifiers
Alias identifiers let you add supplementary identifiers on a best-effort basis, independent of your resolution strategy.
Key benefits:
- Best-effort addition: Skipped if already taken, not an error
- Explicit reporting: Know exactly which were added vs. skipped
- Strategy-independent: Same behavior regardless of resolution strategy
- Operation success: Conflicts don't fail the entire request
How It Works
Esempio di codice
{
"strategy": "first",
"identifiers": [
{"key": "customer_id", "value": "CUST_12345"}
],
"aliasIdentifiers": [
{"key": "emailaddress", "value": "customer@email.com"},
{"key": "phonenumber", "value": "+15551234567"},
{"key": "linkedin_profile", "value": "linkedin.com/in/customer"}
],
"attributes": {
"firstName": "Maria",
"lastName": "Garcia"
}
}
What happens:
- Bird finds or creates contact using customer_id
- For each alias identifier:
- ✅ If available → Added to the contact
- ✅ If already on this contact → Idempotent success
- ⚠️ If on another contact → Skipped, reported in response
Response:
Esempio di codice
{
"contact": {
"id": "contact-uuid-123",
"workspaceId": "workspace-uuid",
"attributes": {
"firstName": "Maria",
"lastName": "Garcia"
}
},
"created": false,
"addedAliases": [
{"key": "emailaddress", "value": "customer@email.com"},
{"key": "linkedin_profile", "value": "linkedin.com/in/customer"}
],
"skippedAliases": [
{"key": "phonenumber", "value": "+15551234567"}
]
}
In this example, the phone number was skipped because it's already associated with a different contact. Your application can then decide whether to
- Log it for manual review
- Update your source system
- Simply accept it (phone genuinely belongs to someone else)
Common Use Cases
Use Case 1: Anonymous to Known User Journey
Scenario: Track anonymous website visitors, then link them to authenticated users.
Challenge: You don't know if the email they provide is already in your system.
Solution:
Step 1: Anonymous visitor browses your site
Esempio di codice
{
"strategy": "first_alias",
"identifiers": [
{"key": "anonymous_id", "value": "anon_xyz789"}
],
"attributes": {
"source": "organic_search",
"visitedPages": ["/products", "/pricing", "/features"],
"firstSeen": "2025-10-22T10:00:00Z"
}
}
Creates a new contact with anonymous ID
Step 2: Visitor signs up with email
Esempio di codice
{
"strategy": "first_alias",
"identifiers": [
{"key": "anonymous_id", "value": "anon_xyz789"}
],
"aliasIdentifiers": [
{"key": "emailaddress", "value": "newcustomer@email.com"}
],
"attributes": {
"signupDate": "2025-10-22T10:15:00Z",
"accountType": "trial"
}
}
Bird finds contact by anonymous_id
Tries to add email:
- If email is new → Added successfully
- If email exists → Skipped
Benefits:
- No data loss if email already exists
- Complete visitor journey preserved
Use Case 2: Multi-Channel Customer Support
Scenario: Customers contact you via phone, email, chat, and social media.
Challenge: Same customer uses different channels, you need unified view.
Solution:
WhatsApp interaction
Esempio di codice
{
"strategy": "first",
"identifiers": [
{"key": "customer_id", "value": "CUST_98765"}
],
"aliasIdentifiers": [
{"key": "phonenumber", "value": "+15559876543"}
],
"attributes": {
"lastContactChannel": "phone",
"lastContactDate": "2025-10-22T09:00:00Z",
"supportTickets": ["TICKET_001"],
"satisfaction": "satisfied"
}
}
Email sign up follow-up
Esempio di codice
{
"strategy": "first",
"identifiers": [
{"key": "customer_id", "value": "CUST_98765"}
],
"aliasIdentifiers": [
{"key": "emailaddress", "value": "customer@company.com"}
],
"attributes": {
"lastContactChannel": "email",
"lastContactDate": "2025-10-22T14:00:00Z",
"supportTickets": ["TICKET_001", "TICKET_002"]
}
}
Live chat session
Esempio di codice
{
"strategy": "first",
"identifiers": [
{"key": "customer_id", "value": "CUST_98765"}
],
"aliasIdentifiers": [
{"key": "chat_handle", "value": "maria_g"}
],
"attributes": {
"lastContactChannel": "chat",
"lastContactDate": "2025-10-22T16:30:00Z",
"chatTranscript": "transcript_link"
}
}
Benefits:
- Single contact record with all channels
- Complete interaction history
- Support agents see full context
Use Case 3: Third-Party Integration
Scenario: Sync data from external systems (CRM, payment processor, marketing tools).
Challenge: External systems have their own IDs, conflicts can occur.
Solution:
Salesforce integration example:
Esempio di codice
{
"strategy": "first_alias",
"identifiers": [
{"key": "salesforce_id", "value": "SF_00Q123456"}
],
"aliasIdentifiers": [
{"key": "emailaddress", "value": "enterprise@client.com"},
{"key": "phonenumber", "value": "+15551234567"},
{"key": "company_id", "value": "COMP_789"}
],
"attributes": {
"source": "salesforce",
"accountValue": 50000,
"industry": "Technology",
"employees": 150,
"lastSyncedAt": "2025-10-22T12:00:00Z"
}
}
Check the response:
Esempio di codice
{
"addedAliases": [
{"key": "emailaddress", "value": "enterprise@client.com"},
{"key": "company_id", "value": "COMP_789"}
],
"skippedAliases": [
{"key": "phonenumber", "value": "+15551234567"}
]
}
Handle conflicts:
- Skipped phone means it's on another contact
- Investigate if it's a duplicate that should be merged on your external system and synced again
- Or accept it (legitimately different contact)
- Log for your integration monitoring
Use Case 4: E-commerce Customer Journey
Scenario: Complete customer lifecycle from browsing to purchase to loyalty.
Solution:
Browse: Visitor adds items to cart
Esempio di codice
{
"strategy": "first",
"identifiers": [
{"key": "device_id", "value": "device_abc123"}
],
"attributes": {
"cartItems": ["product_1", "product_2"],
"cartValue": 89.99,
"browsingCategory": "electronics"
}
}
Checkout: Provides email
Esempio di codice
{
"strategy": "first",
"identifiers": [
{"key": "device_id", "value": "device_abc123"}
],
"aliasIdentifiers": [
{"key": "emailaddress", "value": "shopper@email.com"}
],
"attributes": {
"checkoutStarted": "2025-10-22T10:30:00Z"
}
}
Purchase: Completes order
Esempio di codice
{
"strategy": "first",
"identifiers": [
{"key": "emailaddress", "value": "shopper@email.com"}
],
"aliasIdentifiers": [
{"key": "order_id", "value": "ORDER_2025_10_001"}
],
"attributes": {
"orderCompleted": "2025-10-22T10:45:00Z",
"orderValue": 89.99,
"paymentMethod": "credit_card",
"shippingAddress": "123 Main St..."
}
}
Loyalty: Joins rewards program
Esempio di codice
{
"strategy": "first",
"identifiers": [
{"key": "emailaddress", "value": "shopper@email.com"}
],
"aliasIdentifiers": [
{"key": "loyalty_id", "value": "LOYAL_12345"}
],
"attributes": {
"loyaltyMember": true,
"rewardsPoints": 89,
"memberSince": "2025-10-22"
}
}
Benefits:
- Complete customer journey in one profile
- Marketing can see browsing → purchase conversion
- Customer service sees order and loyalty status
- Analytics show full funnel
Use Case 5: Mobile App + Web Platform
Scenario: Users interact with both your web app and mobile app.
Solution:
Mobile app installation
Esempio di codice
{
"strategy": "first_alias",
"identifiers": [
{"key": "mobile_device_id", "value": "ios_device_xyz"}
],
"attributes": {
"platform": "iOS",
"appVersion": "2.3.1",
"installDate": "2025-10-20",
"pushToken": "push_token_abc..."
}
}
User logs in on mobile
Esempio di codice
{
"strategy": "first_alias",
"identifiers": [
{"key": "mobile_device_id", "value": "ios_device_xyz"}
],
"aliasIdentifiers": [
{"key": "user_id", "value": "USER_456"},
{"key": "emailaddress", "value": "user@email.com"}
],
"attributes": {
"lastLoginMobile": "2025-10-22T08:00:00Z",
"authenticated": true
}
}
User accesses web platform
Esempio di codice
{
"strategy": "first_alias",
"identifiers": [
{"key": "user_id", "value": "USER_456"}
],
"aliasIdentifiers": [
{"key": "web_session_id", "value": "web_sess_123"}
],
"attributes": {
"lastLoginWeb": "2025-10-22T09:00:00Z",
"browser": "Chrome",
"os": "macOS"
}
}
Benefits:
- Cross-platform user tracking
- Can send push notifications using mobile device ID and push token
- Can trigger email using email address
- Unified analytics across platforms
Checking for Conflicts
Always check the skippedAliases field in the response to understand which identifiers couldn't be added:
Response with skipped aliases:
Esempio di codice
{
"contact": {
"id": "contact-abc-123"
},
"addedAliases": [
{"key": "emailaddress", "value": "customer@example.com"}
],
"skippedAliases": [
{"key": "phonenumber", "value": "+15551234567"}
]
}
What to do when aliases are skipped:
- Option 1: Log for monitoring and trend analysis
- Option 2: Create a manual review task for your data quality team
- Option 3: Investigate if the contacts should be merged in your external system
- Option 4: Accept it if the identifier legitimately belongs to another person
Best Practices
1. Choose the Right Strategy for Your Use Case
| Use Case | Recommended Strategy | Why |
|---|---|---|
| Financial/Healthcare data | strict | Data integrity is critical |
| E-commerce customer tracking | first_alias | Progressive identifier collection |
| Analytics/Event tracking | first | Only updating attributes |
| Multi-channel engagement | first_alias | Flexible identifier management |
| High-quality CRM sync | strict | Catch inconsistencies early |
2. Prioritize Your Identifiers Wisely
The order of identifiers matters for strategies that check priority (first_alias, first).
Good prioritization:
Esempio di codice
{
"identifiers": [
{"key": "customer_id", "value": "CUST_123"}, // Most reliable
{"key": "emailaddress", "value": "user@email.com"}, // Very reliable
{"key": "session_id", "value": "sess_xyz"} // Least reliable
]
}
Poor prioritization:
Esempio di codice
{
"identifiers": [
{"key": "session_id", "value": "sess_xyz"}, // Least reliable (BAD!)
{"key": "customer_id", "value": "CUST_123"}, // Most reliable
{"key": "emailaddress", "value": "user@email.com"}
]
}
Why it matters: If session_id changes frequently but is checked first, you might create unnecessary duplicate contacts.
3. Use Alias Identifiers for Supplementary Data
Resolution identifiers = Critical for finding the right contact
Alias identifiers = Nice to have, but not critical
Alias identifiers = Nice to have, but not critical
Esempio di codice
{
"identifiers": [
// Critical: Must have to identify the contact
{"key": "customer_id", "value": "CUST_123"}
],
"aliasIdentifiers": [
// Supplementary: Try to add, but don't fail if you can't
{"key": "linkedin_profile", "value": "..."},
{"key": "twitter_handle", "value": "..."},
{"key": "secondary_email", "value": "..."}
]
}
4. Monitor Skipped Aliases
Track when aliases are being skipped to identify data quality issues:
Warning signs to watch for:
- High skip rate (>20% of aliases skipped): May indicate duplicate contacts in your system
- Specific identifiers always skipped (e.g., certain emails): Suggests a duplicate contact exists
- Skip patterns by source: Some data sources may consistently have conflicts
Actions to take:
- Review skipped aliases regularly to identify duplicate contacts
- Investigate contacts that frequently have identifier conflicts
- Merge duplicate contacts when appropriate in your external system
5. Validate Data Quality
Ensure identifiers are properly formatted before sending:
Email addresses
- ✅ Valid: user@example.com
- ❌ Invalid: user@ (missing domain), @example.com (missing local part), user @email.com (contains space
Phone numbers (E.164 format):
- ✅ Valid: +15551234567
- ❌ Invalid: 555-1234 (missing country code), 15551234567 (missing + prefix), +1 (555) 123-4567 (contains formatting
General rules:
- All identifiers must have non-empty values
- Trim leading/trailing whitespace
- Normalize case (lowercase for emails)
- Use consistent formatting (E.164 for phones)
6. Design for Idempotency
Your integrations should be safe to retry
This is safe to call multiple times
Esempio di codice
{
"identifiers": [
{"key": "customer_id", "value": "CUST_123"}
],
"aliasIdentifiers": [
{"key": "emailaddress", "value": "user@email.com"}
],
"attributes": {
"lastSyncedAt": "2025-10-22T14:30:00Z",
"syncVersion": "v2"
}
}
If called again:
- Same contact is found via customer_id
- Email already present → Reported in addedAliases (not an error)
- Attributes updated with new values
Result: Safe to retry
Troubleshooting Guide
Problem: "Multiple contacts found" Error
Symptom:
Esempio di codice
{
"error": "multiple_contacts_found",
"message": "The provided identifiers match multiple contacts"
}
Cause: Using strict strategy with identifiers that exist on different contacts
Solution:
Option 1: Switch to first_alias strategy if appropriate for your use case.
Option 2: Use only one identifier to resolve, move others to aliases:
Before (causes error)
Esempio di codice
{
"strategy": "strict",
"identifiers": [
{"key": "emailaddress", "value": "user@email.com"}, // On Contact A
{"key": "phonenumber", "value": "+15551234567"} // On Contact B
]
}
After (works)
Esempio di codice
{
"strategy": "first_alias",
"identifiers": [
{"key": "emailaddress", "value": "user@email.com"} // Find Contact A
],
"aliasIdentifiers": [
{"key": "phonenumber", "value": "+15551234567"} // Try to add
]
}
Option 3: Investigate and merge duplicate contacts in your external system if they represent the same person.
Problem: Aliases Always Being Skipped
Symptom:
Esempio di codice
{
"skippedAliases": [
{"key": "emailaddress", "value": "user@email.com"}
]
}
This means the email is already associated with a different contact.
Diagnosis steps:
- Search for the identifier:
GET /v1/contacts/search?emailaddress=user@email.com
This shows you which contact currently has that email.
- Compare contacts:
- Do they represent the same person? → Merge needed
- Do they represent different people? → Accept the skip
- Check your data source:
- Is your source system creating duplicates?
- Do you need data deduplication before sending?
Problem: Creating Duplicate Contacts
Symptom: The same person ends up with multiple contact records.
Cause: Not providing consistent identifiers across API calls.
Example of the problem:
Call 1: Uses email only
Esempio di codice
{
"identifiers": [
{"key": "emailaddress", "value": "user@email.com"}
],
"attributes": {
"firstName": "John"
}
}
Result: Creates Contact A
Call 2: Uses phone only (but doesn't include email!)
Esempio di codice
{
"identifiers": [
{"key": "phonenumber", "value": "+15551234567"}
],
"attributes": {
"lastName": "Doe"
}
}
Result: Creates Contact B (duplicate!)
Solution: Always include at least one consistent identifier across all your API calls:
Call 1
Esempio di codice
{
"identifiers": [
{"key": "user_id", "value": "USER_123"}
],
"aliasIdentifiers": [
{"key": "emailaddress", "value": "user@email.com"}
],
"attributes": {
"firstName": "John"
}
}
Call 2: Same user_id ensures same contact is found
Esempio di codice
{
"identifiers": [
{"key": "user_id", "value": "USER_123"}
],
"aliasIdentifiers": [
{"key": "phonenumber", "value": "+15551234567"}
],
"attributes": {
"lastName": "Doe"
}
}
Result: Finds existing Contact A, adds phone number
Problem: Validation Errors
Symptom:
Esempio di codice
{
"error": "validation_error",
"message": "Invalid identifier format",
"details": {
"key": "emailaddress",
"value": "not-an-email"
}
}
Common validation issues:
Email addresses:
❌ "user@" → Missing domain
❌ "@example.com" → Missing local part
❌ "user @email.com" → Space in email
✅ "user@email.com" → Valid
Phone numbers:
❌ "555-1234" → Missing country code
❌ "15551234567" → Missing + prefix
❌ "+1 (555) 123-4567" → Formatting characters (use digits only)
✅ "+15551234567" → Valid (E.164 format)
Solution: Normalize identifiers in your source system before sending:
For phone numbers:
- Remove all formatting characters (spaces, dashes, parentheses)
- Ensure it starts with + followed by country code
- US example: (555) 123-4567 → +15551234567
For email addresses:
- Convert to lowercase
- Trim leading/trailing whitespace
- Example: USER@EXAMPLE.COM → user@example.com
Problem: Race Conditions with Identifiers
Symptom: The same alias is sometimes added successfully, sometimes skipped (non-deterministic behavior).
Cause: Multiple systems or processes trying to add the same identifier to different contacts simultaneously.
Solution: This is expected behavior when concurrent operations occur:
- Accept eventual consistency:
- The first operation to complete will claim the identifier
- Subsequent operations will see it as skipped
- Check skippedAliases in the response to handle appropriately
- Review patterns:
- If the same identifier is frequently skipped, investigate for duplicate contacts
- Consider whether the conflicting contacts should be merged
Quick Reference
Strategy Comparison
| Strategy | Priority-based? | Add New Identifiers? | Conflict Behavior | Best For |
|---|---|---|---|---|
| strict | No | Yes | ERROR | High-quality data, validation |
| first_alias | Yes | Yes | Skip | Progressive collection |
| first | Yes | No | N/A | Attribute-only updates |
Identifier Priority Guide
High priority (check first):
- 🥇 Customer ID / User ID from your system
- 🥈 Email address (if verified)
- 🥉 Phone number (if verified)
Low priority (check last):
- Session IDs
- Device IDs
- Temporary identifiers
Alias Identifiers Decision Tree
Do you need explicit reporting of success/failure?
├─ YES → Use aliasIdentifiers
└─ NO
└─ Will conflicts occur frequently?
├─ YES → Use aliasIdentifiers
└─ NO → Use regular identifiers with first_alias strategy
Common Patterns
Pattern 1: Anonymous → Known
Resolution: anonymous_id
Aliases: emailaddress (when user signs up)
Strategy: first_alias
Pattern 2: Multi-Channel
Resolution: customer_id
Aliases: channel-specific identifiers
Strategy: first_alias
Pattern 3: External Sync
Resolution: external_system_id
Aliases: emailaddress, phonenumber, etc.
Strategy: first_alias (or strict for high-quality data)
Pattern 4: Analytics Only
Resolution: user_id
Aliases: None
Strategy: first