One contact, one account. That's how Salesforce is built, and for most businesses, it works. But if you sell to staffing firms, consultancies, or partner networks, the same person shows up in three, five, sometimes ten accounts. The default breaks the moment a recruiter switches agencies, a partner rep covers multiple resellers, or a consultant runs projects across your client base.

One Contact, Many Accounts Mastering the Salesforce Account and Contact Relationship

The Salesforce account and contact relationship is a one-to-many link. One account can have many contacts, but each contact belongs to a single account unless you change how the objects connect. There are three ways to fix this: turn on the AccountContactRelation object, deliberately duplicate a contact when the accounts are genuinely separate, or use the Individual object when privacy compliance is the driver.

This guide covers how the default relationship works under the hood, how the three options compare, how to enable Contacts to Multiple Accounts, and how to report on cross-account relationships without breaking your dashboards.

How the default account and contact relationship works in Salesforce

Every contact in Salesforce points to one account through a field called AccountId. That single field is the entire relationship. It's a lookup field on the Contact object, which makes the default one-to-many: one account holds many contacts, but each contact belongs to a single account.

For teamssending email from Salesforce, this default is the invisible foundation of every campaign list you build. Filter a campaign by account, and Salesforce is filtering by AccountId. Segment by industry, region, or account tier, and every contact rolls up through this one field. When the model matches your business, campaigns target the right people, and reporting stays clean.

How the Default Account–Contact Relationship Works

The AccountId field and how the link is stored

AccountId is a standard field on every Contact record. Assign a contact to an account, and Salesforce writes that account's ID into AccountId. That's the entire link.

There's no bridge table, no join object. Just a foreign key on the Contact side pointing up to Account. Move a contact to a different account, and you overwrite the AccountId, wiping the previous relationship with no history. For email teams, that overwrite is wherecampaign lists start getting stale: the contact is now filed under a new account, but the previous account's segments, campaign memberships, and engagement history all still reference the old link.

Is it a lookup or a master-detail relationship?

Neither, exactly. AccountId on Contact looks like a lookup but behaves like a hybrid. Salesforce calls it a "special" lookup, and the special part matters when you're troubleshooting deletes, ownership, or why a contact stopped receiving emails.

BehaviorStandard lookupStandard master-detailContact the Account
Cascade deleteNoYesConfigurable
Owner cascading (UI)NoYesNo
Owner cascading (Apex)NoYesPossible
Contact can exist without a parentYesNoYes (private contact)
Contact record typeStandardDetailStandard

Three behaviors explain most of the "why did this happen?" questions email teams ask when campaigns misfire.

Cascade delete

Delete an account in the UI, and its contacts move to the Recycle Bin with it, which quietly removes them from every active campaign they were in. API-level deletes and restores don't always cascade cleanly, which bites teams during data migrations and cleanup jobs. Rule of thumb: trust cascade in the UI; test it in code before running any bulk operation against a production list.

Owner cascading

Contacts have their own OwnerId, separate from the account owner. Change the account owner, and contact owners stay put. This matters for email routing rules that use the contact owner as the sender, or for teams that segment campaigns by rep. Ownership drift is a real problem in accounts with team turnover, and it shows up as emails going out with the wrong "from" name months after the actual handoff.

Private contacts

Salesforce allows a contact with no AccountId, called a private contact. Common uses include personal referrals, individual donors not tied to a household record, or consumers in a B2C setup. Private contacts don't show up in account-based campaign filters. Miss this, and your "email all contacts in tier-1 accounts" campaign quietly excludes anyone in a private state.

Account and contact relationship vs. account hierarchy

The account and contact relationship connects people to accounts. Account hierarchy connects accounts to other accounts. Use the first when one person works with multiple companies. Use the second when one company is structured as a parent with subsidiaries. Account hierarchy relies on the ParentId field on child accounts to roll them up under a parent. Account and contact relationship uses the Contacts to Multiple Accounts feature and the AccountContactRelation object to link a single contact to more than one account.

When you need both

Both often show up in the same customer. A university system uses a hierarchy for its campuses. A student who transfers between campuses is a contact tied to two accounts. Hierarchy solves the first. Contacts to Multiple Accounts solves the second.

The wrong move is forcing a hierarchy to solve the contact problem. File a shared contact under the parent account, and campaigns targeted at a specific campus miss it.

Quick test

You need to link...Use
Parent company to its subsidiariesAccount hierarchy
One contact to multiple accountsContacts to Multiple Accounts (AccountContactRelation)
Both are in the same customerBoth, together

Set up hierarchy first, then enable Contacts to Multiple Accounts. Doing it the other way around means rebuilding AccountContactRelation records after any hierarchy cleanup.

Three ways to model a contact who works across accounts

Salesforce gives you three options when the default one-to-one link doesn't fit: turn on the AccountContactRelation object to link one contact to many accounts, duplicate the contact when the accounts are separate businesses, or use the Individual object when privacy law is the driver. Each option changes how campaigns target the person, how opt-outs behave, and how reports count them.

The three options, side by side

Duplicate the contactAccountContactRelationIndividual object
What it doesSeparate contact record under each accountLinks one contact to multiple accounts through a junction objectStores consent and preferences at a person level, separate from accounts
Best forAccounts are truly separate, and each rep needs their own recordOne person works with, donates to, studies at, or is placed at multiple accountsPrivacy compliance (GDPR, CCPA) requires consent to be tracked per person
Campaign listsPerson appears once per accountPerson appears once, with account context attachedPerson appears once, consent governs every send
Opt-out handlingLocal to each record, no cascadeCentral to the contact, respected everywhereCentral to the individual, overrides account preferences
ReportingThe same person in multiple rows inflates countsSingle contact rolls up across all linked accountsPerson-level view, decoupled from accounts
Setup effortLowMediumHigh

Option 1: Deliberate duplication

Use duplication when the accounts genuinely have no relationship, and each one needs to own the person's engagement separately. A consultant who works with three clients who shouldn't see each other's history. A staffing candidate was placed at three companies, each managed by a different rep.

The catch: opt-outs stay local, so an unsubscribe on one record doesn't cover the others. Unique-contact counts inflate.

Option 2: AccountContactRelation

The right answer for most teams. Turn on Contacts to Multiple Accounts, and Salesforce activates the AccountContactRelation junction object, which lets one contact link to any number of accounts. Campaigns target the person once. Opt-outs cover every linked account. Custom report types built on AccountContactRelation show engagement across every account the person touches.

Fits higher ed (a student who's also an alumnus), nonprofits (a donor active with two chapters), financial services (an advisor across household accounts), and any B2B where partners or consultants overlap accounts.

The mechanics of the junction object (primary account handling, roles, private contacts) are covered next.

Option 3: The Individual object

Use it when privacy compliance is the primary driver. GDPR and CCPA require consent to be tracked per person, independent of any account link. Consent on the Individual record governs every send, no matter how many contact records reference the person.

Setup is heavy: fields mapped between Contact and Individual, consent capture built into every intake surface, reporting redesigned around the Individual. Worth it when compliance is non-negotiable. Overkill for most operational contact management.

How to pick

  1. Is privacy compliance the main driver? Use the Individual object.
  2. Do the accounts need to stay isolated for this person? Duplicate.
  3. Any other reason? Use AccountContactRelation.

AccountContactRelation: the junction object behind related contacts

AccountContactRelation is a standard Salesforce object that stores the many-to-many link between contacts and accounts. Turn on Contacts to Multiple Accounts, and Salesforce creates one AccountContactRelation record for every contact-account pair. Each record holds the account ID, contact ID, a Roles field, an active flag, and IsDirect, which marks the primary relationship.

The contact record still uses AccountId to point to its primary account. Every additional account link lives as a separate AccountContactRelation record.

How the primary account works

Every contact has one primary account, stored in the AccountId field on the Contact. That primary account gets an AccountContactRelation record with IsDirect = true. Every other linked account gets an AccountContactRelation record with IsDirect = false, called an indirect relationship.

The consequence for email teams: filtering a campaign by AccountId returns only contacts whose primary account matches. Every indirect relationship is silently excluded. Filter through AccountContactRelation instead to catch both.

Contact vs. Related Contact: What's actually different

Related Contact is not a separate object. It's the term Salesforce uses in the UI for a contact whose relationship to the current account is indirect (IsDirect = false). Same contact record, different view.

ContactRelated Contact
MeaningContact filed under this account as its primaryContact whose primary account is a different account
AccountIdPoints to this accountPoints to a different account
IsDirect on AccountContactRelationTrueFalse
Shows up inContacts related listRelated Contacts related list
Campaign filter by AccountIdIncludedExcluded
Campaign filter through AccountContactRelationIncludedIncluded

Campaign lists built the traditional way (filter by account, add all contacts) silently miss every Related Contact. A partner rep who works with three of your accounts but is filed under a fourth gets excluded from every account-based campaign at the first three.

Private contacts and AccountContactRelation

A private contact (no AccountId) can still hold AccountContactRelation records linking it to specific accounts. This creates a common list-building gap: the contact is excluded from any AccountId-based filter (AccountId is blank) but included in AccountContactRelation-based filters.

Rule of thumb: if your database has any private contacts, run segmented sends through AccountContactRelation filters, not AccountId.

How to enable Contacts to Multiple Accounts

Contacts to Multiple Accounts is enabled from Salesforce Setup in three steps: turn it on in Account Settings, add the Related Contacts and Related Accounts lists to your page layouts, and start creating relationships from either side. The feature is available onall Salesforce editions that include the standard Contact object and takes about ten minutes to configure. Existing contact records are not affected until you actively add relationships.

How to enable Contacts to Multiple Accounts in Salesforce

Step 1: Turn it on in account settings

Go to Setup, search for Account Settings, and open it. Check the box for Allow users to relate a contact to multiple accounts and save. The AccountContactRelation object becomes available immediately across the org.

Nothing else happens automatically. No existing contact records get new relationships, no campaign lists change, and no reports break. The feature is on, but the org still behaves exactly as before until you use it.

Step 2: Add the related lists to page layouts

Two related lists need to be added:

  • Related Contacts on the Account page layout shows every contact linked to this account, direct or indirect.
  • Related Accounts on the Contact page layout show every account this contact is linked to, directly or indirectly.

For each page layout you use, go to the layout editor, drag the related list into place, and save. Do this for every account and contact page layout across every profile that will use the feature. Skip a layout, and reps on that layout won't see the relationships even though the data exists.

Step 3: Create a relationship from the related contacts list

From any Account page, open the Related Contacts list and click Add Relationship. Search for the contact, pick the role, mark active or inactive, and save. Salesforce writes an AccountContactRelation record linking the contact to this account as an indirect relationship. The contact's primary account (AccountId) stays unchanged.

You can do the same in reverse from the Contact page using the Related Accounts list. Either direction creates the same AccountContactRelation record.

What to do next for campaigns and reporting

The feature being on doesn't fix yourcampaign lists. Existing filters built on AccountId only catch primary account relationships. Any list-based send that needs to reach indirect contacts has to be rebuilt to filter through AccountContactRelation.

Two things to update before the next send:

  • Campaign filters: switch account-based segments from Contact.AccountId to AccountContactRelation lookups so you include indirect contacts.
  • Custom report types: create report types with AccountContactRelation as the primary object to see cross-account engagement rolled up per person.

Turn on the feature without doing these two steps, and campaigns still miss the same people they missed before.

Reporting on account and contact relationships

To report on account and contact relationships in Salesforce, build custom report types on the AccountContactRelation object. Standard contact and account reports only show primary relationships through AccountId, so every indirect contact linked through Contacts to Multiple Accounts stays invisible until you use an AccountContactRelation-based report type.

The three custom report types you need

Salesforce ships one custom report type for AccountContactRelation and lets you build two more. Together they cover the three angles you'll need.

Custom report typePrimary objectShows
Contacts with Related AccountsContactEvery account each contact is linked to. Best for "who works with more than one account" analysis.
Accounts with Related ContactsAccountEvery contact is linked to each account. Best for campaign list validation.
AccountContactRelations with RolesAccountContactRelationEvery relationship with account, contact, role, and active status. Best for role-based segmentation.

Each takes about ten minutes through Setup → Report Types. Add the fields you need (Role, IsDirect, Active, campaign membership) and save.

Where the Roles field fits

The Roles field lives on AccountContactRelation, not on Contact. Standard values include Business User, Decision Maker, Economic Buyer, Evaluator, Executive Sponsor, Influencer, and Technical Buyer. Contact reports won't show Roles because it's not on the Contact object. The AccountContactRelations with Roles report type is the only way to count contacts by role across accounts or segment sends by role.

What breaks if you skip this step

Turn on Contacts to Multiple Accounts, add relationships, and run a standard contact report to check the setup. The report shows contacts filtered by primary account only. Every indirect relationship is invisible. Teams often assume the feature isn't working, roll it back, and rebuild it wrong the second time.

Custom report types aren't optional. They're how you see that the data you set up actually exists.

Targeting related contacts across accounts in MassMailer

The default account and contact relationship works when contacts belong to one company. The moment they don't, you have three options: turn on AccountContactRelation for most cases, duplicate the contact when accounts are truly separate, and use the Individual object when privacy compliance drives the decision. Once you set up the model, custom report types on AccountContactRelation let you see and act on the data.

MassMailer runs natively inside Salesforce, so it respects the AccountContactRelation setup as-is. Campaign lists built through AccountContactRelation filters catch every indirect relationship. Opt-outs sync to the contact record and cover every linked account.

Role-based segmentation works with the same custom report types you build for internal reporting. You do not re-map, re-sync, or re-import anything.

Start a 15-day free trial →