Overview
The customization system allows you to extend the user interface by adding custom buttons, panels, field links, and visual styling to various parts of the application. These customizations are entity-specific and can be configured to appear in different contexts based on user permissions, system state, and custom conditions.
Four Types of Customizations
- Custom Buttons โ Interactive actions in data grids and details
- Custom Panels โ Additional information panels in the editor interface
- Custom Links โ Field-level links to external systems based on record data
- Column Colours โ Conditional cell background colors in data grids
card: Custom Buttons
Interactive buttons that appear in data grids or data details and can execute custom actions on selected records. Support URL opening with context variables or running automated workflows.
card: Custom Panels
Collapsible panels that appear in the editor interface to display additional information, embed external content, or provide custom controls for enhanced workflows.
card: Custom Links
Field-level links that appear on editor fields and open external applications with context data. Visible only when field has a value and optional conditions are met.
card: Column Colours
Conditional background colors for data grid cells based on filter expressions. Apply to all columns or specific columns for visual data highlighting.
Key Capabilities
- Entity-specific โ Attach customizations to any data entity
- Context-aware โ Access user info, selected records, and system state
- Conditional visibility โ Show/hide based on custom filter expressions
- Changeset & readonly aware โ Respect system modes and permissions
Custom Buttons [badge:Buttons|warning]
Interactive buttons that enhance data list or data detail functionality
[try:/customButtons|Manage Custom Buttons โ|right]
Key Features
- Appear in data grids next to standard action buttons
- Execute custom actions on selected records
- Support both single and multiple record selection
- Can be conditionally shown based on record state
- Respect changeset and readonly mode restrictions
Configuration Fields
Basic Properties
nameโ Button label displayed to usersentityIdโ Target entity for the buttoniconโ Icon displayed on the buttoncolorโ Button color theme
Behavior
allowMultipleโ Whether button works with multiple selected recordsconditionโ Optional filter expression to enable/disable buttonactionโ The action type: “openUrl” or “runAutomation”urlโ Target URL (for openUrl action)automation_idโ Target automation (for runAutomation action)
Visibility Control
allowInChangeSetโ Show button when changeset is activeallowInReadOnlyโ Show button in readonly mode
Action Types
openUrl โ Open URL Action
Opens a URL in the browser with contextual information from the UI. This allows for powerful custom integrations and external system connections.
Available Context Variables:
{user.id}โ Current user ID{user.email}โ Current user email{selectedIds}โ Comma-separated list of selected record IDs{entityId}โ Target entity identifier{orgId}โ Current organization ID
Example URL:
https://external-system.com/api/export?records={selectedIds}&user={user.id}&org={orgId}
runAutomation โ Run Automation Action
Executes a predefined automation workflow on the selected records. This enables complex data processing, transformations, and business logic execution.
Automation Capabilities:
- Data modification and updates
- Field calculations and transformations
- Integration with external systems
- Batch processing operations
- Workflow trigger execution
Example Use Cases:
- Bulk price updates based on cost calculations
- Automated inventory synchronization
- Customer data enrichment workflows
- Report generation and distribution
Example Configurations
OpenUrl Action Example:
{
"name": "Export to PDF",
"entityId": "products",
"icon": "FileText",
"color": "blue",
"allowMultiple": true,
"allowInChangeSet": false,
"allowInReadOnly": true,
"condition": "status = 'active'",
"action": "openUrl",
"url": "https://export.company.com/pdf?ids={selectedIds}&user={user.id}"
}
RunAutomation Action Example:
{
"name": "Update Prices",
"entityId": "products",
"icon": "euro",
"color": "green",
"allowMultiple": true,
"allowInChangeSet": true,
"allowInReadOnly": false,
"condition": "category.code = 'ELEC'",
"action": "runAutomation",
"automation_id": "code:bulk-price-update-automation"
}
Custom Panels [badge:Panels|info]
Collapsible panels that extend the editor interface
[try:/customPanels|Manage Custom Panelsโ|right]
Key Features
- Appear in the editor sidebar alongside standard panels
- Collapsible with coordinated expand/collapse behavior
- Can display custom content, data, or controls
- Support different positioning (left, right, top, bottom)
- Can appear in list view, detail view, or both
- Support for data-independent panels with requiresData option
- Respect changeset and readonly mode restrictions
Configuration Fields
Basic Properties
nameโ Panel title displayed to usersentityIdโ Target entity for the paneliconโ Icon displayed in panel headerpositionโ Panel placement (left, right, top, bottom)locationโ Where to show the panel (list, detail, both)sizeโ Panel size (tiny, small, medium, large)
Content & Behavior
actionโ Action type: “openUrl” or “showHtml”bodyโ HTML content to display (for showHtml action)urlโ Target URL (for openUrl action)requiresDataโ Whether panel depends on selected dataconditionโ Optional filter expression to show/hide panel
Visibility Control
allowInChangeSetโ Show panel when changeset is activeallowInReadOnlyโ Show panel in readonly mode
Action Types
openUrl โ Open URL Action
Opens a URL in the browser with contextual information from the UI, same as CustomButtons. This allows for external integrations and dynamic content based on current context.
Supports the same context variables as CustomButtons:
{user.id},{user.email}โ Current user information{selectedIds}โ Selected record IDs{entityId},{orgId}โ Context identifiers
โ ๏ธ Important: Iframe Embedding Requirements
When the URL is loaded in an iframe within the application, the target server must be properly configured:
- `X-Frame-Options: ALLOW-FROM {HOSTNAME}` โ Allow embedding from your server
- `Content-Security-Policy: frame-ancestors 'self' {HOSTNAME}` โ Modern CSP alternative
- HTTPS required if the parent application uses HTTPS (mixed content policy)
- Cookies may not work properly due to SameSite restrictions in cross-origin iframes
showHtml โ Show HTML Action
Displays the content from the body field as HTML within the panel. This enables rich formatted content directly in the interface.
HTML Limitations:
- Limited HTML subset is supported for security
- JavaScript is not allowed
- External script tags and event handlers are filtered out
- Safe tags like headings, paragraphs, lists, and basic formatting are supported
Example HTML Body:
<h3>Product Information</h3><p>Additional details about this product...</p><ul><li>Feature 1</li><li>Feature 2</li></ul>
Data Dependencies
requiresData Property
Controls whether the panel depends on currently selected data. When set to false, the panel can be displayed even when no data is selected, making it independent of the current selection state.
requiresData: trueโ Panel only appears when data is selected. Context variables like selectedIds will be available.requiresData: falseโ Panel can appear independently. Useful for help text, static information, or global actions.
Example Configurations
ShowHtml Action Example:
{
"name": "Product Help",
"entityId": "products",
"icon": "HelpCircle",
"position": "right",
"location": "detail",
"size": "small",
"requiresData": false,
"allowInChangeSet": true,
"allowInReadOnly": true,
"action": "showHtml",
"body": "<h3>Product Guidelines</h3><p>Follow these steps when editing products...</p>"
}
OpenUrl Action Example:
{
"name": "Product Analytics",
"entityId": "products",
"icon": "BarChart",
"position": "right",
"location": "detail",
"size": "medium",
"requiresData": true,
"allowInChangeSet": true,
"allowInReadOnly": true,
"action": "openUrl",
"url": "https://analytics.company.com/product?id={selectedIds}&user={user.id}"
}
Visibility Control
Understanding when customizations are shown or hidden
System States
Changeset Mode
When a changeset is active, only customizations with allowInChangeSet: true are visible.
Readonly Mode
When in readonly mode, only customizations with allowInReadOnly: true are visible.
Visibility Matrix
| Mode | allowInChangeSet | allowInReadOnly | Visible |
|---|---|---|---|
| Normal | - | - | โ |
| Changeset Active | true | - | โ |
| Changeset Active | false | - | โ |
| Readonly | - | true | โ |
| Readonly | - | false | โ |
Iframe Embedding Considerations
Important technical requirements and limitations when embedding external content
โ ๏ธ Critical Server Configuration Requirements
External URLs loaded in custom panels must be specifically designed for iframe embedding. The target server MUST provide proper HTTP security headers to allow embedding.
Required HTTP Headers
Critical โ X-Frame-Options Header:
X-Frame-Options: ALLOW-FROM {HOSTNAME}
Use your actual application domain. This header allows your application to embed the external content in an iframe.
Modern Alternative โ Content Security Policy (CSP):
Content-Security-Policy: frame-ancestors 'self' {HOSTNAME}
Modern browsers prefer CSP over X-Frame-Options. This directive controls which domains can embed the page in frames. Replace with your actual application domain.
Recommended โ Additional Security Headers:
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Referrer-Policy: strict-origin-when-cross-origin
Additional security headers that improve the security posture of embedded content.
Common Iframe Problems & Solutions
HTTPS Mixed Content
Problem: Browser blocks HTTP content when parent page uses HTTPS
Solution: Ensure all external URLs use HTTPS protocol. Modern browsers require secure connections for iframe embedding.
โ
https://external-app.com/panel
โ http://external-app.com/panel
Cookie/Session Issues
Problem: Authentication cookies don’t work in cross-origin iframes
Solution: Use SameSite=None; Secure for cookies that need to work in iframes, or implement token-based authentication through URL parameters.
Frame Busting Scripts
Problem: JavaScript code prevents iframe embedding
Solution: Remove or modify scripts that check window.top !== window.self or similar frame-busting logic.
Responsive Design
Problem: Content doesn’t adapt well to iframe constraints
Solution: Design iframe-specific layouts or use responsive CSS that works well in constrained spaces. Consider the panel size settings (tiny, small, medium, large).
Communication
Problem: Limited communication between iframe and parent
Solution: Use postMessage API for secure cross-origin communication if the embedded content needs to interact with the parent application.
Server Configuration Examples
๐ Domain Configuration โ replace {HOSTNAME} with your actual application domain.
Apache (.htaccess):
Header always append X-Frame-Options "ALLOW-FROM {HOSTNAME}"
Header always set Content-Security-Policy "frame-ancestors 'self' {HOSTNAME}"
Header always set X-Content-Type-Options "nosniff"
Header always set X-XSS-Protection "1; mode=block"
Nginx:
add_header X-Frame-Options "ALLOW-FROM {HOSTNAME}" always;
add_header Content-Security-Policy "frame-ancestors 'self' {HOSTNAME}" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
Node.js/Express:
app.use((req, res, next) => {
res.setHeader('X-Frame-Options', 'ALLOW-FROM {HOSTNAME}');
res.setHeader('Content-Security-Policy', "frame-ancestors 'self' {HOSTNAME}");
res.setHeader('X-Content-Type-Options', 'nosniff');
res.setHeader('X-XSS-Protection', '1; mode=block');
next();
});
๐ก Testing Iframe Compatibility: Before deploying, test your external URL by creating a simple HTML file with an iframe pointing to your content. Open it in a browser and check the developer console for any frame-related errors.
Custom Links [badge:Links|info]
Field-level links that appear on editor fields and open external applications with context data
[try:/customLinks|Manage Custom Links โ|right]
What are Custom Links good for?
Custom Links allow you to add contextual links to specific fields in the editor interface. These links can open external applications, search databases, or navigate to related systems, all populated with data from the current record.
- Add links directly to field labels, icons next to inputs, or buttons below fields
- Open external applications with context from the current record (e.g., name, ID, user info)
- Links are visible only when the selected field has a value
- Support conditional display based on filter expressions
- Respect changeset and readonly mode restrictions
Common Use Cases
๐ Link to CRM System
Add a link on the customer name field that opens the customer record in your CRM system.
๐ Search EAN Database
Add a link on the EAN field to search for product information in an external database.
๐ Open on E-commerce
Add a link to view the product on your e-commerce platform’s frontend.
Link Positions
Custom Links can appear in three different positions relative to the field:
Label Position
The field label becomes a clickable link. When clicked, it opens the external URL. This is useful for making the entire label interactive.
Icon Position
A small icon button appears after the input field. Multiple icon links can appear side by side. This is useful for providing quick access without changing the field’s appearance.
Under Position
Link appears as a small text link below the input field. Multiple links can wrap to multiple lines. This is useful for secondary actions that don’t need immediate visibility.
Configuration Fields
Basic Properties
nameโ Link text displayed to usersentityIdโ Target entity for the linkcolumnsโ Array of field IDs where the link should appeariconโ Icon displayed with the link (for icon and under positions)positionโ Where to show the link: “label”, “icon”, or “under”
Action Configuration
actionโ Action type (currently only “openUrl” is supported)urlโ Target URL template with variable placeholders
Conditional Display
conditionโ Optional filter expression to show/hide the linkallowInChangeSetโ Show link when changeset is activeallowInReadOnlyโ Show link in readonly mode
URL Template Variables
The URL can contain placeholders that are replaced with actual data when the link is clicked:
Record Data
{data.fieldName}โ Value of any field from the current record (e.g.,{data.name},{data.ean}){objectIds}โ Current record ID{entityId}โ Entity identifier
User Information
{user.id}โ Current user ID{user.username}โ Current user’s username{user.email}โ Current user’s email address
System Information
{language}โ Current UI language code{orgId}โ Current organization ID
Example URL Template:
https://crm.example.com/customer?name={data.name}&email={data.email}&lang={language}&user={user.username}
Visibility Rules
โ ๏ธ Important: Field Value Requirement
Custom Links are **only visible when the associated field has a value**. If the field is empty (null, undefined, or empty string), the link will not appear, even if all other conditions are met.
Conditional Display Example
You can use filter expressions to show links only when specific conditions are met:
platform.code = 'shoptet'
This link will only appear when the product is on the Shoptet platform.
Example Configuration
Complete Custom Link Example:
{
"name": "View in CRM",
"entityId": "products",
"columns": ["name", "ean"],
"icon": "ExternalLink",
"position": "icon",
"action": "openUrl",
"url": "https://crm.example.com/product?ean={data.ean}&name={data.name}&user={user.email}",
"condition": "platform.code = 'shoptet' AND status = 'active'",
"allowInChangeSet": false,
"allowInReadOnly": true,
"disabled": false
}
This link appears as an icon next to the “name” and “ean” fields when the product is on the Shoptet platform, is active, and the field has a value. It opens the CRM with the product’s EAN, name, and current user’s email.
๐ก Best Practices
- Use icon position for frequently accessed links to keep the UI clean
- Use label position when the link is the primary action for that field
- Use under position for secondary or less common actions
- Keep link names short and descriptive
- Test URL templates with different record data to ensure they work correctly
- Use conditions to show links only when they're relevant
- Consider using `allowInReadOnly=true` for view-only links
Column Colours [badge:Colours|success]
Conditional background colors for data grid cells
[try:/columnColours|Manage Custom Colours โ|right]
Key Features
- Apply background colors to data grid cells based on filter conditions
- Target all columns or specific columns in an entity
- Multiple color rules can be defined per entity
- Evaluated in real-time as data changes
- Great for visual highlighting of important data (e.g., overdue items, stock levels)
Configuration Fields
Basic Properties
nameโ Descriptive name for the color ruleentityIdโ Target entity for the color rulecolourโ Background color (hex format, e.g., #ff0000)descriptionโ Optional description of the rule
Filtering
filterโ SQL-like condition that determines when to apply the color- Example:
status = 'overdue' AND priority = 'high'
- Example:
Column Targeting
allColumnsโ Apply color to all columns in the rowcolumnsโ Array of specific column names to color (if allColumns is false)- Example:
["price", "discount", "total"]
- Example:
Control
disabledโ Temporarily disable the color rule without deleting it
Use Cases
Status Highlighting
Highlight rows based on status values. For example, show overdue tasks in red, completed tasks in green, and in-progress tasks in yellow.
Example Configuration:
Entity: tasks
Filter: status = 'overdue'
Colour: #ffcccc (light red)
All Columns: true
Threshold Alerts
Highlight specific columns when values exceed thresholds. For example, highlight the stock column in red when inventory falls below minimum levels.
Example Configuration:
Entity: products
Filter: stock < minimumStock
Colour: #ff6666 (red)
All Columns: false
Columns: ["stock"]
Priority Visualization
Use different colors for different priority levels to help users quickly identify high-priority items in large datasets.
Example Configuration:
Entity: orders
Filter: priority = 'urgent'
Colour: #ffe6e6 (light red)
All Columns: true
Financial Indicators
Highlight financial data based on conditions, such as negative balances, outstanding payments, or profit margins below targets.
Example Configuration:
Entity: invoices
Filter: balance < 0
Colour: #fff3cd (light yellow)
All Columns: false
Columns: ["balance", "status"]
Behavior & Precedence
Evaluation Order
Column color rules are evaluated for each row in the grid. If multiple rules match a row, the last matching rule (in the order they appear in the database) is applied.
Performance Considerations
Column colors are evaluated in real-time as data changes. Keep filter expressions simple and efficient for best performance, especially on large datasets.
Disabled Rules
Use the disabled field to temporarily turn off color rules without deleting them. This is useful for testing or seasonal adjustments.
๐ก Best Practices
- Use subtle colors that don't interfere with text readability
- Limit the number of color rules per entity to avoid visual clutter
- Test color combinations for accessibility (contrast ratios)
- Give rules descriptive names to help maintain them later
- Consider user preferences - some users may be color-blind
Implementation Notes
Performance
Customizations are loaded and filtered efficiently using React hooks with proper dependency management and atomic state updates to prevent UI flickering.
Security
All customizations respect the underlying permission system and entity access controls. Users can only see and interact with customizations for entities they have access to.