Junction objects
On this page
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 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, which holds two fields:
| Field | Points at |
|---|---|
s_c__Content_Block_Id__c |
Content Block |
s_c__Page_Id__c |
Page |
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 records how much of an order item a shipment covers. Some join three things rather than two: Promotion 2 Condition 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.
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, 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 | Product2 and Product Category |
| Product Tag | Product2 and Tag |
| Product Media | Product2 and Media |
| Product Tax | Product2 and Tax |
| Product Tax Group | Product2 and Tax Group |
| Product Variant | Product2 and Product2, for variant sets |
| Related Product | Product2 and Product2 |
| Related Product Category | Product Category and Product Category |
| Product Category Hierarchy | Product Category and Product Category, for nesting |
| Account Product Category | Account and Product Category |
| Supplier Account | Account and Product2 |
Content and design
| Junction | Joins |
|---|---|
| Content Block Page | Content Block and Page |
| Content Block Product | Content Block and Product2 |
| Content Block Article | Content Block and Article |
| Content Block Product Category | Content Block and Product Category |
| Content Block Child | Content Block and Content Block, for nesting |
| Articles Article Categories | Article and Article Category |
| Article Tag | Article and Tag |
| Page Tag | Page and Tag |
| Related Article | Article and Article |
| Related Page | Page and Page |
Customers and access
| Junction | Joins |
|---|---|
| Membership Article | Membership and Article |
| Membership Page | Membership and Page |
| Location Group Account | Account and Location Group |
Shipping zones and geography
| Junction | Joins |
|---|---|
| Zone Country | Zone and Country |
| Zone State | Zone and State |
| Zone City | Zone and City |
| Zone Postcode | 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 | Product2 and Fulfillment Category |
| Fulfillment Category Station | Fulfillment Category and Fulfillment Station |
| Outlet Stock Location | Outlet and Stock Location |
| Store Stock Location | Store and Stock Location |
| Product Delivery Window | Product2 and Delivery Window |
| Fulfillment Item | Order Item and Shipment, with an optional Asset |
| Cart Fulfillment Item | Cart Fulfillment and Cart Item, the pre-order equivalent |
Orders, payments, and promotions
| Junction | Joins |
|---|---|
| Voucher Payment | Voucher and Payment |
| Order Item Reward | Order Item and Reward |
| Cart Promotion 2 | Cart and Promotion 2 |
| Tax Tax Group | Tax and Tax Group |
| Payment Item | Payment and Order Item, so one payment can cover several items |
| Allocated Fulfillment Payment | Fulfillment Item and Payment Item |
| Order Item Tax | Order Item and Tax |
| Promotion 2 Condition | Promotion 2 with a Condition and a Reward |
| Permitted Restricted Item | Order Item and Permitted Restricted Product |
Store configuration and POS
| Junction | Joins |
|---|---|
| Store Form | Store and Form |
| Product Form | Product2 and Form |
| Store Campaign | Store and Campaign |
| Store Feed | Store and Feed |
| Product Bookable Location | Product2 and Bookable Location |
| Register Shift User | Register Shift and User |
| Outlet User | 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.
Was this article helpful?
Thanks for your feedback! It helps us improve our docs.