POS layouts
On this page
POS layouts control how records are displayed and interacted with in the StoreConnect POS. Each layout targets a specific Salesforce object and defines which fields appear, what filters staff can use, and what actions are available.
Layouts are configured in Salesforce and consumed by the POS automatically based on their identifier — the value that tells the POS where to place the layout in the interface.
Layout types
POS layouts come in four types, set via the Type field on the Pos_Layout__c record:
| Type | Description |
|---|---|
| List | Displays multiple records in a scrollable list. Supports filters, search, and record-click actions. |
| Record | Displays a single record’s fields in a detail view. |
| Form | Presents an editable form. Used for data entry workflows like the end-of-shift form and customer form. |
| Grid | Displays action items arranged in rows, columns, and pages. Used for home screens and product category grids. |
:::note List and grid layouts load data at render time. They do not update automatically if records change while the layout is open — staff need to navigate away and back, or apply a filter, to see updated records. :::
Layout fields
Layout fields (Pos_Layout_Field__c) define which fields appear on a layout and in what order. Each field record belongs to a layout and specifies:
- Field Name — the API name of the Salesforce field to display. Must exist on the layout’s object, or be a custom data mapping field accessed as
data.field_name. - Display Name — the label shown in the POS. Supports Liquid template syntax (for example,
{{ record.name }}). Defaults to the field name in sentence case if left blank. - Position — a number controlling display order (ascending).
- POS View — optionally renders a custom Liquid view instead of the raw field value.
Custom views on layout fields
Any layout field on any layout type can reference a POS View (Pos_View__c). When a view is assigned, the POS renders the view’s Liquid template instead of a standard field value or input control.
:::warning
In list and grid layouts, field views are pre-rendered in batch for all visible records at once. As a result, <script> tags inside a field view template are not executed. If your view requires scripting, use a layout-level view instead (assign the view to the layout record, not to an individual field).
:::
Views have access to the following Liquid variables:
| Variable | Description |
|---|---|
{{ record.field_name }} |
Any field on the current record |
{{ record.id }} |
Record ID |
{{ record.name }} |
Record name |
{{ record.image.small_url }} |
Thumbnail image URL |
{{ record.image.large_url }} |
Full-size image URL |
{{ record.pricing.price | money }} |
Formatted price |
{{ record.data.field_name }} |
Custom data mapping fields |
{{ record.account.data.field_name }} |
Nested relationship field access |
Example: display a product image
liquid
{% if record.image %}
<img src="{{ record.image.small_url }}" alt="{{ record.name }}" />
{% endif %}
Example: price with sale badge
liquid
{{ record.pricing.price | money }}
{% if record.data.on_sale %}
<span class="badge">Sale</span>
{% endif %}
Action items
Three action item slots are available on every layout, configured via lookup fields on the Pos_Layout__c record:
| Field | Placement | Works with |
|---|---|---|
| Primary Action Item | Button at the bottom of the layout | All layout types |
| Secondary Action Item | Button at the top left of the layout | All layout types |
| Record Action Item | Triggered when a staff member taps a record row | List layouts only |
Each slot references a Pos_Action_Item__c record, which defines the action, label, appearance, and optional child group.
Action item properties
| Property | Description |
|---|---|
| Display Name | Button or menu label. Supports Liquid template syntax. |
| Type | action — a single button that triggers an action. group — opens a child action group when tapped. |
| Action | The action identifier to execute (e.g., cart:add_product). Required for action type. |
| Params | Action parameters expressed as Liquid (evaluated against the current record). |
| Icon | An icon shown on the button (e.g., bag, plus_circle, home, people, cog, more). |
| Color | Hex color for the button (e.g., #4a90e2). |
| Image | A custom image asset displayed on the button. |
| Position | Sort order within a group. |
| Child Action Group | The action group to display when this item is tapped (for group type). |
| Next Action Item | An action to trigger automatically after this one completes, receiving context from the result. |
:::tip Use the Record Action Item to make list rows interactive — for example, opening a detail view or adding a product to the cart when a staff member taps a row. :::
Action chaining
Action items can be chained using the Next Action Item lookup. When the primary action completes successfully, the POS automatically triggers the next action and passes along context from the result.
For example, a cart:add_product action can chain to a modal:open action. The next action’s params can reference {{ cart_item_sc_id }} — the cart item ID returned by the add.
:::note If the primary action fails, the chain stops and the next action does not trigger. An error is surfaced to the POS interface. :::
Action types reference
The following action identifiers are available for use in Pos_Action_Item__c records. All params support Liquid template syntax, evaluated against the current record.
Cart actions
| Action | Description | Key params |
|---|---|---|
cart:add_product |
Add a product to the cart | See detail below |
cart:add_contact |
Assign a contact to the cart | contact_sc_id |
cart:remove_contact |
Remove the assigned contact from the cart | — |
cart:resume |
Resume a parked cart | — |
cart:discount |
Open the cart discount flow | — |
cart:item_update |
Update a cart item | — |
cart:item_remove |
Remove an item from the cart | — |
cart:add_product params
| Param | Type | Description |
|---|---|---|
product_id |
String | Product Salesforce ID |
product_code |
String | Product code (alternative to product_id) |
quantity |
Integer | Quantity to add (default: 1) |
unit_price |
Decimal | Override the unit price |
unit_discount |
Decimal | Apply a discount to the unit price |
serial_numbers |
Array | Serial numbers to assign to the cart line item |
name |
String | Override the display name in the cart |
pending |
Boolean | Mark the item as pending |
Example: add product from the current record with quantity and price from custom fields
liquid
product_id={{ record.id }}
quantity={{ record.s_c__Quantity__c }}
unit_price={{ record.s_c__Price__c }}
After cart:add_product completes, the context passed to a chained next action includes product_id and cart_item_sc_id.
Navigation actions
| Action | Description | Key params |
|---|---|---|
nav:home |
Navigate to the home screen | — |
nav:customers |
Open the customers list | — |
nav:customers:create |
Open the create customer form | — |
nav:customers:update |
Open a customer’s edit form | customer_id |
nav:contacts |
Open the contacts list | — |
nav:products |
Open the products list | — |
nav:orders |
Open the orders list | — |
nav:carts |
Open the carts list | — |
nav:fulfillments |
Open fulfillments / pickups | — |
nav:suppliers |
Open the suppliers list | — |
nav:labels |
Open the labels list | — |
nav:stock_requests |
Open stock requests | — |
nav:stock_adjustments |
Open stock adjustments | — |
nav:settings |
Open POS settings | — |
nav:layout |
Navigate to a custom layout | layout (layout identifier) |
nav:session_start_user |
Start a session for a specific user | user_id |
nav:session_add_user |
Add a user to the current session | — |
nav:session_end |
End the current shift | — |
nav:disconnect_register |
Disconnect the register | — |
Modal actions
| Action | Description | Key params |
|---|---|---|
modal:open |
Open a custom POS View in a modal | view_identifier |
modal:close |
Close the current modal | — |
modal:open:email_receipt |
Open the email receipt modal | — |
modal:open:return |
Open the return / refund flow | — |
modal:open:url |
Load a URL in a modal | url |
modal:open:alert |
Display an alert modal | — |
Record actions
| Action | Description | Key params |
|---|---|---|
record:save |
Save the current form record | — |
record:delete |
Delete the current record | — |
open:layout |
Open a layout for a specific record | layout (identifier), record_id |
Print actions
| Action | Description |
|---|---|
print:receipt |
Print the receipt |
print:template |
Print using a label or receipt template |
print:labels |
Print labels |
print:email_receipt |
Email the receipt |
System actions
| Action | Description |
|---|---|
lock |
Lock the POS and return to user login |
sync |
Trigger a data sync |
close |
Close or go back |
pay_by_link:generate |
Generate a pay-by-link payment |
printer:remove |
Remove the connected printer |
Action groups
Action groups define the POS navigation menus, sidebar, top bar, home screen grid, and other interface areas. They are configured separately from layouts and work by grouping action items into named containers placed at specific locations in the POS UI.
| See [[pos-action-groups | POS action groups]] for full configuration details, system identifiers, and how to create nested menus. |
Grid layouts
Grid layouts (type: Grid) display records as cards in a visual grid. They are used for the home screen, product quick-access panels, and category grids.
Grid cards are auto-filled — the POS arranges cards automatically based on the records returned. No manual row, column, or page positioning is required.
Each card displays the layout fields you configure (for example, a product image, name, and price). Use POS Views on fields to render custom Liquid content inside each card.
Tapping a grid card
Use the Record Action Item on the grid layout to define what happens when staff tap a card. A common pattern is to open a record layout showing the item’s detail:
action: open:layout
params: layout=my_record_layout;record_id={{ record.id }}
When staff tap a card to open a detail view, the grid stays mounted in the background. Search, filters, and scroll position are preserved when the detail view closes.
Layout-level view on a grid
You can assign a POS View to the grid layout itself (not just to individual fields). When set, the view’s Liquid template replaces the default card rendering for each record, giving you full control over card HTML.
Layout filters
| Filters can be added to List type layouts to let staff narrow down records. Filter configuration, including auto-generated options, is covered in [[pos-layout-filters | POS layout filters]]. |
System layouts
The following layout identifiers are reserved for specific POS screens. Create a Pos_Layout__c record with a matching identifier to customise that screen.
Contact and customer layouts
| Identifier | Type | Object | Purpose |
|---|---|---|---|
contact_list |
List | Contact | Customer list view |
contact_record |
Record | Contact | Customer detail view |
customer_form |
Form | Contact | Create or edit customer form |
Cart layouts
| Identifier | Type | Object | Purpose |
|---|---|---|---|
cart_contact_list |
List | Contact | Contact selection within the cart |
cart_record |
Record | Cart | Cart detail view |
delivery_address |
Record | Cart | Delivery address entry |
delivery_rates |
Record | Cart | Delivery rate selection |
Order layouts
| Identifier | Type | Object | Purpose |
|---|---|---|---|
order_list |
List | Order | Order list view |
order_record |
Record | Order | Order detail view |
Product layouts
| Identifier | Type | Object | Purpose |
|---|---|---|---|
product_record |
Record | Product | Product detail view |
Shift layouts
| Identifier | Type | Object | Purpose |
|---|---|---|---|
end_shift_form |
Form | Shift | End-of-shift form presented when ending a shift |
:::note
Form type layouts (customer_form, end_shift_form) extend the standard built-in forms. Layout fields you add appear alongside the default fields. Assign a POS View to a field to render custom Liquid content in place of a standard input.
:::
Legacy layout view override
The built-in POS layouts for products, carts, customers, and orders (used when no custom layout record is configured) also support a layout-level view override. When a Pos_View__c is assigned to one of these legacy layouts, the view replaces the content area of the layout. The header — including the search bar, filters, and action buttons — remains visible.
This lets you customise the display of built-in screens without creating a full replacement layout.
Layout identifier convention
From v21, all POS layout identifiers use snake_case (underscores) as the standard naming convention. If you have existing layouts or action groups using dash-case identifiers (e.g., cart-contact-list), those continue to work, but the POS will log a deprecation warning to the browser console when a dash-case fallback is used.
Update existing identifier values in Salesforce to the snake_case equivalents at your convenience to clear the warnings.
:::note
The backward-compatibility fallback converts underscores to dashes when looking up a record that is not found by its snake_case identifier. This means identifiers with underscores automatically fall back to their dash-case equivalent. Identifiers that do not contain underscores (such as end_shift_form) were already stored in snake_case and are not affected.
No removal date for this fallback has been set. Dash-case identifiers will continue to trigger a deprecation warning indefinitely until updated. :::
Common identifier migration reference
Layout identifiers
| New (snake_case) | Old (dash-case) |
|---|---|
cart_contact_list |
cart-contact-list |
cart_contact_record |
cart-contact-record |
cart_list |
cart-list |
cart_record |
cart-record |
contact_record |
contact-record |
customer_form |
customer-form |
customer_list |
customer-list |
customer_record |
customer-record |
end_shift_form |
end-shift-form |
order_list |
order-list |
order_record |
order-record |
product_list |
product-list |
product_record |
product-record |
Action group identifiers
| New (snake_case) | Old (dash-case) |
|---|---|
sidebar_main_menu |
sidebar-main-menu |
sidebar_fixed_menu |
sidebar-fixed-menu |
topbar_main_menu |
topbar-main-menu |
register_actions |
register-actions |
session_start_actions |
session-start-actions |
session_actions |
session-actions |
View identifiers
| New (snake_case) | Old (dash-case) |
|---|---|
modal_view |
modal-view |
:::tip
To check whether a layout, action group, or view is using a deprecated identifier, open the browser developer console on the POS and look for messages in the format: Using deprecated identifier 'old-identifier'. Please use 'new_identifier' instead.
:::
Creating a POS layout
- In Salesforce, open the POS Layouts object (search for it in the App Launcher).
- Click New.
- Complete the layout record:
- Name — an internal name for the layout
- Display Name — the name shown to staff in the POS (supports Liquid template syntax)
- Type — List, Record, Form, or Grid
- Identifier — the value that places the layout in the POS UI (use a system identifier for built-in screens, or a custom value for custom views)
- Object Name — the API name of the Salesforce object this layout applies to
- Description — optional notes for administrators
- Save the layout record.
- In the POS Layout Fields related list, add the fields to display.
-
For List layouts, optionally add filters via the POS Layout Filters related list. See [[pos-layout-filters POS layout filters]]. - Optionally, assign action items using the Primary Action Item, Secondary Action Item, and Record Action Item lookup fields.
- Optionally, assign a POS View to render a fully custom Liquid view for the entire layout, instead of the default display.
Initial filter and sort
For List layouts, the Pos_Layout__c record accepts initial filter and sort values that apply before staff interact with the layout:
| Field | Format | Example |
|---|---|---|
| Filter | Semicolon-separated key=value pairs. Use commas to separate multiple values for multiselect fields. |
status=active;type=standard |
| Sort | Semicolon-separated field:direction pairs |
name:asc;created_date:desc |
The filter key can reference standard Salesforce fields or custom data mapping fields (e.g., data.customer_type).
These values set the default state of the layout when it first loads. Staff can apply additional filters on top of these defaults but cannot clear values set here through the standard filter controls.
Object reference
| For a full field listing, see [[pos-layout-object-reference | POS Layout Object Reference]], [[pos-layout-field-object-reference | POS Layout Field Object Reference]], and [[pos-layout-filter-object-reference | POS Layout Filter Object Reference]]. |