ney entry points as versioned artifacts. Define the trigger object, filter conditions, and resolution path in a structured configuration format. This enables infrastructure-as-code deployment and environment promotion.
interface CrmJourneyEntryConfig {
entrySource: 'Salesforce';
triggerObject: 'Opportunity' | 'Lead' | 'Case' | 'User';
filterCriteria: {
field: string;
operator: 'equals' | 'contains' | 'greater_than';
value: string | number;
};
contactResolution: {
lookupChain: string[];
emailField: string;
subscriberKeyField: string;
};
reentryPolicy: 'no_reentry' | 'reentry_on_event';
deduplicationWindow: number; // minutes
}
const onboardingTrigger: CrmJourneyEntryConfig = {
entrySource: 'Salesforce',
triggerObject: 'Opportunity',
filterCriteria: {
field: 'StageName',
operator: 'equals',
value: 'Closed Won'
},
contactResolution: {
lookupChain: ['Primary_Contact__r', 'Contact'],
emailField: 'Email',
subscriberKeyField: 'Id'
},
reentryPolicy: 'no_reentry',
deduplicationWindow: 5
};
Step 2: Establish the Subscriber Resolution Path
Journey Builder requires a deterministic path from the trigger object to a valid email subscriber. The resolution chain must traverse relationship fields that exist in both CRM and SFMC data extensions. If the chain breaks, the entry event is silently dropped or fails with a routing error.
function resolveSubscriberPath(
crmRecord: Record<string, any>,
chain: string[]
): { email: string; subscriberKey: string } | null {
let current = crmRecord;
for (const segment of chain) {
if (!current || !current[segment]) {
console.warn(`Resolution chain broken at: ${segment}`);
return null;
}
current = current[segment];
}
const email = current.Email;
const key = current.Id;
if (!email || !key) {
console.warn('Missing required subscriber attributes');
return null;
}
return { email, subscriberKey: key };
}
Step 3: Configure Idempotency and Re-Entry Logic
CRM objects frequently toggle between states during negotiation, escalation, or correction workflows. Without explicit re-entry controls, a single customer can be injected into the journey multiple times, causing duplicate communications and brand fatigue.
Set the contact entry mode to No Re-entry for lifecycle campaigns (onboarding, activation, renewal). Use Re-entry on Event only for transactional or recurring triggers (e.g., monthly billing reminders, quarterly health checks). The deduplication window should align with expected CRM state stabilization time.
Step 4: Deploy via MC Connect Routing
MC Connect acts as the event bus between Salesforce CRM and SFMC. When a record matches the filter criteria, the platform serializes the event payload, validates the contact resolution path, and injects the subscriber into the journey queue. No custom API calls or middleware are required. The routing layer handles authentication, rate limiting, and payload transformation automatically.
Architecture Rationale:
- Native Entry Source over Custom API: Reduces authentication overhead, enforces schema validation, and leverages Salesforce's event delivery guarantees.
- Explicit Resolution Chain: Prevents silent failures and enables predictable debugging when relationship fields change.
- Idempotency by Default: Protects customer experience from CRM state churn without requiring post-injection deduplication logic.
- Configuration-Driven Deployment: Enables version control, environment promotion, and automated testing across sandboxes.
Pitfall Guide
1. Broken Subscriber Resolution Chain
Explanation: The trigger object lacks a direct relationship to a Contact with a populated email field. Journey Builder cannot map the CRM record to an SFMC subscriber, resulting in dropped entries or silent failures.
Fix: Validate the lookup chain against both CRM schema and SFMC data extension mappings. Use a fallback resolution strategy or explicit error logging when intermediate relationships are null.
2. Unintended Journey Re-Entry
Explanation: CRM records toggle between states (e.g., Closed Won β Reopened β Closed Won). Each match injects the subscriber again, causing duplicate emails and journey duplication.
Fix: Configure Contact Entry Mode: No Re-entry for lifecycle campaigns. Implement a custom status flag in SFMC if historical re-entry tracking is required.
3. Filter Logic Drift
Explanation: Picklist values, case sensitivity, or whitespace differences cause filter mismatches. A trigger configured for Closed Won may fail if the CRM uses closed won or includes trailing spaces.
Fix: Normalize filter values during configuration. Use exact match operators and validate against CRM metadata exports. Implement pre-deployment schema validation scripts.
4. Sandbox-to-Production Configuration Drift
Explanation: Journey settings, data extension mappings, and contact resolution paths are manually recreated in production, leading to mismatches in field names, relationship IDs, or re-entry policies.
Fix: Export journey configurations as JSON/YAML artifacts. Use deployment pipelines to promote identical configurations across environments. Validate field mappings against production metadata before activation.
5. Missing Email Validation & Suppression Handling
Explanation: Entries are injected without verifying email deliverability or suppression status. Invalid addresses bounce, damaging sender reputation and skewing journey analytics.
Fix: Integrate a pre-injection validation step or leverage SFMC's built-in suppression lists. Route invalid entries to a quarantine data extension for manual review.
6. Timezone & Date Filter Misalignment
Explanation: Date-based triggers (e.g., CreatedDate > 24 hours ago) fail when CRM and SFMC operate in different timezones or when daylight saving transitions occur.
Fix: Standardize all date filters to UTC. Use platform-native timezone conversion functions or store timestamps as epoch values to eliminate regional drift.
7. Over-Reliance on Real-Time Without Fallback
Explanation: Network partitions, MC Connect throttling, or CRM API limits can delay event delivery. Journeys with strict SLAs fail when real-time routing is unavailable.
Fix: Implement a secondary batch reconciliation job that runs hourly. Compare CRM state against journey entry logs and inject missing subscribers via the SFMC REST API.
Production Bundle
Action Checklist
Decision Matrix
| Scenario | Recommended Approach | Why | Cost Impact |
|---|
| One-time lifecycle campaign (onboarding, activation) | No Re-entry + Real-time trigger | Prevents duplicate communications; aligns with single-state change | Low (native routing) |
| Recurring transactional flow (billing, renewal) | Re-entry on Event + Deduplication window | Allows periodic injection while preventing rapid-fire duplicates | Medium (requires monitoring) |
| High-volume CRM object (Lead, Case) | Batch reconciliation + Real-time primary | Mitigates API throttling; ensures 100% coverage during peak loads | Medium-High (engineering overhead) |
| Complex relationship chain (multi-level lookup) | Pre-injection validation + Quarantine routing | Fails fast on broken paths; preserves sender reputation | Low-Medium |
Configuration Template
{
"journeyEntry": {
"source": "Salesforce",
"trigger": {
"object": "Opportunity",
"filter": {
"field": "StageName",
"operator": "equals",
"value": "Closed Won"
}
},
"resolution": {
"chain": ["Primary_Contact__r", "Contact"],
"email": "Email",
"subscriberKey": "Id"
},
"policy": {
"reentry": "no_reentry",
"deduplicationMinutes": 5,
"timezone": "UTC"
},
"fallback": {
"enabled": true,
"batchWindowMinutes": 60,
"quarantineExtension": "JourneyEntryFailures"
}
}
}
Quick Start Guide
- Create a connected sandbox pair: Link a Salesforce CRM sandbox to an SFMC sandbox/non-production Business Unit. Ensure MC Connect is active and data extensions are provisioned.
- Define the entry configuration: Use the JSON template above to specify the trigger object, filter, resolution chain, and re-entry policy. Import into Journey Builder via the Salesforce Entry Source.
- Inject a test record: Create a CRM record matching the filter criteria. Verify that the contact appears in the journey audience and that the first communication is queued within 3 minutes.
- Validate edge cases: Test records with missing relationships, invalid emails, and repeated state changes. Confirm that broken resolutions route to quarantine and that re-entry policies prevent duplicates.
- Promote to production: Export the validated configuration, apply it to the production journey, and activate. Monitor the first 24 hours of entries for resolution success rates and delivery latency.