# Junction objects

Source: https://support.storeconnect.com/articles/junction-objects · Last modified 21 August 2026

Salesforce cannot link two records directly in a **many-to-many** relationship,
where each side can have many of the other. A product belongs to several
categories, and a category holds several products. One-to-one and one-to-many
relationships are a plain lookup field on the record; many-to-many needs a record
in between.

StoreConnect solves this the standard Salesforce way, with a **junction object**:
a small record in the middle holding a relationship field to each side. If you
have come from relational databases, this is the join table you would expect, and
the two relationship fields are its foreign keys. Salesforce calls it a junction
object, and StoreConnect names these records after the two things they join, so
that is the term used here.

Use this article when a relationship you expect to find on an object is not
there. Most of the time it is on a junction, one step away.

## Why a content block is not on the page

The clearest example is the one that surprises people most often. Open the
[Content Block](content-block-object-reference) object and you will find lookups
to **Media** and nothing else. There is no **Page** field. Yet content blocks
plainly appear on pages.

The link lives on [Content Block Page](content-blocks-pages-object-reference),
which holds two fields:

| Field | Points at |
|-------|-----------|
| `s_c__Content_Block_Id__c` | [Content Block](content-block-object-reference) |
| `s_c__Page_Id__c` | [Page](page-object-reference) |

One record per block-on-a-page. Put the same block on three pages and you get
three of these records, each with its own **Position**, so the same block can sit
in a different place on each page.

Every object reference article now has a **Referenced by** section listing the
records that point at it, with an **Also links to** column naming what a join
record connects it to. That is the fastest way to answer "what is this related
to?" for any object.

## Recognizing one

A junction object in StoreConnect usually has all three of these:

- **A name made of the things it joins.** `Product_Tag__c`, `Zone_Country__c`,
  `Content_Blocks_Pages__c`, `Membership_Article__c`.
- **A relationship field to each side**, named `<Thing>_Id__c`.
- **Few fields of its own.** Often just **Position** or a quantity, sometimes
  nothing at all.

None of those is absolute. Some junctions carry real data: a
[Fulfillment Item](fulfillment-item-object-reference) records how much of an
order item a shipment covers. Some join three things rather than two:
[Promotion 2 Condition](promotion2-condition-object-reference) pairs a condition
and a reward with a promotion. And some are named for what they represent rather
than for both sides, like [Payment Item](payment-item-object-reference).

Equally, an object with two lookups is not automatically a junction. **Address**
points at both **Account** and **Contact**, but it is a record in its own right
with a street, city, and postcode. The test is purpose, not shape: would the
record still mean anything if you removed the links? For a junction, no.

## Master-detail or lookup

Junctions use both, and the difference matters when you delete something.

- **Master-detail** ties the junction's life to its parent. Delete the parent and
  the junction records go with it. On
  [Content Block Page](content-blocks-pages-object-reference), the **Page** side
  is master-detail, so deleting a page removes its placements, leaving the
  content blocks themselves untouched.
- **Lookup** leaves the junction behind. The field simply empties.

Check the **Relationships** table on the object reference article before you
delete anything in bulk. The **Type** column tells you which behavior applies.

## Working with junctions

**Querying.** You cannot reach across a junction in one hop. To list the
categories a product belongs to, query the junction and traverse from there:

```sql

SELECT s_c__Category_Id__r.Name
FROM s_c__Products_Product_Categories__c
WHERE s_c__Product_Id__c = '01t...'
```

**Importing.** Create both sides first, then the junction records. A junction
row with an unresolved key fails, and master-detail junctions cannot be created
before their master exists at all. Use `s_c__sC_Id__c` external IDs to reference
records you have just loaded rather than looking up Salesforce IDs.

**Counting.** A junction row is one relationship, not one product. Reporting on
`Products_Product_Categories__c` counts placements; a product in four categories
contributes four rows.

## Junction objects in StoreConnect

Grouped by the area they belong to. Each links to its object reference, where the
**Relationships** and **Referenced by** tables give the field names and types.

### Catalog

| Junction | Joins |
|----------|-------|
| [Product Product Category](products-product-categories-object-reference) | Product2 and Product Category |
| [Product Tag](product-tag-object-reference) | Product2 and Tag |
| [Product Media](product-media-object-reference) | Product2 and Media |
| [Product Tax](product-tax-object-reference) | Product2 and Tax |
| [Product Tax Group](product-tax-group-object-reference) | Product2 and Tax Group |
| [Product Variant](product-variant-object-reference) | Product2 and Product2, for variant sets |
| [Related Product](related-product-object-reference) | Product2 and Product2 |
| [Related Product Category](related-product-category-object-reference) | Product Category and Product Category |
| [Product Category Hierarchy](product-category-hierarchy-object-reference) | Product Category and Product Category, for nesting |
| [Account Product Category](account-product-category-object-reference) | Account and Product Category |
| [Supplier Account](product-supplier-object-reference) | Account and Product2 |

### Content and design

| Junction | Joins |
|----------|-------|
| [Content Block Page](content-blocks-pages-object-reference) | Content Block and Page |
| [Content Block Product](content-blocks-products-object-reference) | Content Block and Product2 |
| [Content Block Article](content-blocks-articles-object-reference) | Content Block and Article |
| [Content Block Product Category](content-blocks-product-categories-object-reference) | Content Block and Product Category |
| [Content Block Child](content-blocks-children-object-reference) | Content Block and Content Block, for nesting |
| [Articles Article Categories](articles-article-categories-object-reference) | Article and Article Category |
| [Article Tag](article-tag-object-reference) | Article and Tag |
| [Page Tag](page-tag-object-reference) | Page and Tag |
| [Related Article](related-article-object-reference) | Article and Article |
| [Related Page](related-page-object-reference) | Page and Page |

### Customers and access

| Junction | Joins |
|----------|-------|
| [Membership Article](membership-article-object-reference) | Membership and Article |
| [Membership Page](membership-page-object-reference) | Membership and Page |
| [Location Group Account](location-group-account-object-reference) | Account and Location Group |

### Shipping zones and geography

| Junction | Joins |
|----------|-------|
| [Zone Country](zone-country-object-reference) | Zone and Country |
| [Zone State](zone-state-object-reference) | Zone and State |
| [Zone City](zone-city-object-reference) | Zone and City |
| [Zone Postcode](zone-postcode-object-reference) | Zone and Postcode |

A zone is built from whichever of these four you need. They are separate
junctions rather than one, because a zone can mix levels: a whole country plus a
handful of individual postcodes.

### Fulfillment and inventory

| Junction | Joins |
|----------|-------|
| [Product Fulfillment Category](product-fulfillment-category-object-reference) | Product2 and Fulfillment Category |
| [Fulfillment Category Station](fulfillment-category-station-object-reference) | Fulfillment Category and Fulfillment Station |
| [Outlet Stock Location](outlet-stock-location-object-reference) | Outlet and Stock Location |
| [Store Stock Location](store-stock-location-object-reference) | Store and Stock Location |
| [Product Delivery Window](product-delivery-window-object-reference) | Product2 and Delivery Window |
| [Fulfillment Item](fulfillment-item-object-reference) | Order Item and Shipment, with an optional Asset |
| [Cart Fulfillment Item](cart-fulfillment-item-object-reference) | Cart Fulfillment and Cart Item, the pre-order equivalent |

### Orders, payments, and promotions

| Junction | Joins |
|----------|-------|
| [Voucher Payment](voucher-payment-object-reference) | Voucher and Payment |
| [Order Item Reward](order-item-reward-object-reference) | Order Item and Reward |
| [Cart Promotion 2](cart-promotion2-object-reference) | Cart and Promotion 2 |
| [Tax Tax Group](tax-tax-group-object-reference) | Tax and Tax Group |
| [Payment Item](payment-item-object-reference) | Payment and Order Item, so one payment can cover several items |
| [Allocated Fulfillment Payment](allocated-fulfillment-payment-object-reference) | Fulfillment Item and Payment Item |
| [Order Item Tax](order-items-taxes-object-reference) | Order Item and Tax |
| [Promotion 2 Condition](promotion2-condition-object-reference) | Promotion 2 with a Condition and a Reward |
| [Permitted Restricted Item](permitted-restricted-item-object-reference) | Order Item and Permitted Restricted Product |

### Store configuration and POS

| Junction | Joins |
|----------|-------|
| [Store Form](store-form-object-reference) | Store and Form |
| [Product Form](product-form-object-reference) | Product2 and Form |
| [Store Campaign](store-campaign-object-reference) | Store and Campaign |
| [Store Feed](store-feed-object-reference) | Store and Feed |
| [Product Bookable Location](product-bookable-location-object-reference) | Product2 and Bookable Location |
| [Register Shift User](register-shift-user-object-reference) | Register Shift and User |
| [Outlet User](outlet-user-object-reference) | Outlet and User, with the user's Outlet User Type |

You should now be able to look at any object reference article, see from its
**Referenced by** table which junctions point at it, and follow the **Also links
to** column to whatever sits on the other side.

---

## Follow StoreConnect

- [Email Newsletter](https://getstoreconnect.com/c/lp-newsletter)
- [LinkedIn Newsletter](https://www.linkedin.com/build-relation/newsletter-follow?entityUrn=7444956928444862464)
- [YouTube](https://www.youtube.com/channel/UCngKdP2x8l1wcbAKW3tvU8g)
- [LinkedIn](https://www.linkedin.com/company/storeconnect)
- [X / Twitter](https://x.com/storeconnecthq)

## Popular Links

- [Partners](https://getstoreconnect.com/partners)
- [News](https://getstoreconnect.com/articles/news)
- [Events](https://getstoreconnect.com/articles/events)
- [Feature Comparison](https://getstoreconnect.com/how-we-compare)
- [Download a free trial](https://appexchange.salesforce.com/appxListingDetail?listingId=a0N3A00000FMkeKUAT)
- [Book a Demo](https://getstoreconnect.com/contact)

## Documentation

- [Help documentation](https://support.storeconnect.com/help-documentation)
- [AI agents](https://support.storeconnect.com/ai)
- [Videos & tutorials](https://support.storeconnect.com/videos-tutorials)
- [Developer reference](https://support.storeconnect.com/developer-reference)
- [Release notes](https://support.storeconnect.com/release-notes)
- [Troubleshooting](https://support.storeconnect.com/troubleshooting)
- [Trust Center](https://trust.getstoreconnect.com/)
- [Status Page](https://status.storeconnect.com/)

## Contact

- info@getstoreconnect.com
- US +1 415 745 3230
- AUS +61 2 8365 2308

100 S Ashley Dr, Suite 600-2461
Tampa FL 33602-600 USA

Level 22, Sydney Place
180 George Street
Sydney, NSW, 2000, AUS

---

StoreConnect Support — https://support.storeconnect.com/articles/junction-objects