sf-industry-commoncore-omniscript: OmniStudio OmniScript Creation and Validation
Expert OmniStudio OmniScript builder for declarative, step-based guided digital experiences. OmniScripts are the OmniStudio analog of Screen Flows: multi-step, interactive processes that collect input, orchestrate server-side logic (Integration Procedures, DataRaptors), and present results to the user — all without code.
Quick Reference
Scoring: 120 points across 6 categories. Thresholds: ✅ 90+ (Deploy) | ⚠️ 67-89 (Review) | ❌ <67 (Block - fix required)
Core Responsibilities
- OmniScript Generation: Create well-structured OmniScripts from requirements, selecting appropriate element types for each step
- Element Design: Configure PropertySetConfig JSON for each element with correct data binding, validation, and conditional logic
- Dependency Analysis: Map all references to Integration Procedures, DataRaptors, and embedded OmniScripts before deployment
- Data Flow Analysis: Trace data through the OmniScript JSON structure — from prefill through user input to final save actions
CRITICAL: Orchestration Order
sf-industry-commoncore-omnistudio-analyze → sf-industry-commoncore-datamapper → sf-industry-commoncore-integration-procedure → sf-industry-commoncore-omniscript → sf-industry-commoncore-flexcard (you are here: sf-industry-commoncore-omniscript)
OmniScripts consume Integration Procedures and DataRaptors. Build those FIRST. FlexCards may launch OmniScripts — build FlexCards AFTER. Use sf-industry-commoncore-omnistudio-analyze to map the full dependency tree before starting.
Key Insights
| Insight |
Details |
| Type/SubType/Language triplet |
Uniquely identifies an OmniScript. All three values are required and form the composite key. Example: Type=ServiceRequest, SubType=NewCase, Language=English |
| PropertySetConfig |
JSON blob containing all element configuration — layout, data binding, validation rules, conditional visibility. This is where the real logic lives |
| Core namespace |
OmniProcess with IsIntegrationProcedure = false (equivalently OmniProcessType='OmniScript'). Elements are child OmniProcessElement records |
| Element hierarchy |
Elements use Level/Order fields for tree structure. Level 0 = Steps, Level 1+ = elements within steps. Order determines sequence within a level |
| Version management |
Multiple versions can exist; only one can be active per Type/SubType/Language triplet. Activate via the IsActive field |
| Data JSON |
OmniScripts pass a single JSON data structure through all steps. Elements read from and write to this shared JSON via merge field syntax |
Workflow Design (5-Phase Pattern)
Phase 1: Requirements Gathering
Before building, evaluate alternatives: OmniScripts are best for complex, multi-step guided processes. For simple single-screen data entry, consider Screen Flows. For data display without interaction, consider FlexCards.
Ask the user to gather:
- Type: The process category (e.g.,
ServiceRequest, Enrollment, ClaimSubmission)
- SubType: The specific variation (e.g.,
NewCase, UpdateAddress, FileAppeal)
- Language: Typically
English unless multi-language support is required
- Purpose: What business process this OmniScript guides the user through
- Target org: Org alias for deployment
- Data sources: Which objects/APIs need to be queried or updated
Then: Check existing OmniScripts to avoid duplication, identify reusable Integration Procedures or DataRaptors, and map the dependency chain.
Phase 2: Design & Element Selection
Design each step and select element types appropriate to the interaction pattern.
Container Elements
| Element Type |
Purpose |
Key Config |
| Step |
Top-level container for a group of UI elements; each Step is a page in the wizard |
chartLabel, knowledgeOptions, show (conditional visibility) |
| Conditional Block |
Show/hide a group of elements based on conditions |
conditionType, show expression |
| Loop Block |
Iterate over a data list and render elements for each item |
loopData (JSON path to array) |
| Edit Block |
Inline editing container for tabular data |
editFields, dataSource |
Input Elements
| Element Type |
Purpose |
Key Config |
| Text |
Single-line text input |
label, placeholder, pattern (regex validation) |
| Text Area |
Multi-line text input |
label, maxLength, rows |
| Number |
Numeric input with optional formatting |
label, min, max, step, format |
| Date |
Date picker |
label, dateFormat, minDate, maxDate |
| Date/Time |
Date and time picker |
label, dateFormat, timeFormat |
| Checkbox |
Boolean toggle |
label, defaultValue |
| Radio |
Radio button group for single selection |
label, options (static or data-driven) |
| Select |
Dropdown selection |
label, options, optionSource (static/data) |
| Multi-select |
Multiple item selection |
label, options, maxSelections |
| Type Ahead |
Search/autocomplete input |
label, dataSource, searchField, minCharacters |
| Signature |
Signature capture pad |
label, penColor, backgroundColor |
| File |
File upload |
label, maxFileSize, allowedExtensions |
| Currency |
Currency input with locale formatting |
label, currencyCode, min, max |
| Email |
Email input with format validation |
label, placeholder |
| Telephone |
Phone number input with masking |
label, mask, placeholder |
| URL |
URL input with format validation |
label, placeholder |
| Password |
Masked text input |
label, minLength |
| Range |
Slider input |
label, min, max, step |
| Time |
Time picker |
label, timeFormat |
Display Elements
| Element Type |
Purpose |
Key Config |
| Text Block |
Static content display (HTML supported) |
textContent, HTMLTemplateId |
| Headline |
Section heading |
text, level (h1-h6) |
| Aggregate |
Calculated summary display |
aggregateExpression, format |
| Disclosure |
Expandable/collapsible content |
label, defaultExpanded |
| Image |
Image display |
imageURL, altText |
| Chart |
Data visualization |
chartType, dataSource |
Action Elements
| Element Type |
Purpose |
Key Config |
| DataRaptor Extract Action |
Pull data from Salesforce |
bundle, inputMap, outputMap |
| DataRaptor Load Action |
Push data to Salesforce |
bundle, inputMap |
| Integration Procedure Action |
Call server-side Integration Procedure |
ipMethod (Type_SubType), inputMap, outputMap, remoteOptions |
| Remote Action |
Call Apex @RemoteAction or REST |
remoteClass, remoteMethod, inputMap |
| Navigate Action |
Page navigation or redirection |
targetType, targetId, URL |
| DocuSign Envelope Action |
Trigger DocuSign envelope |
templateId, recipientMap |
| Email Action |
Send email |
emailTemplateId, recipientMap |
Logic Elements
| Element Type |
Purpose |
Key Config |
| Set Values |
Variable assignment and data transformation |
elementValueMap (key-value pairs) |
| Validation |
Input validation rules with custom messages |
validationFormula, errorMessage |
| Formula |
Calculate values using formula expressions |
expression, dataType |
| Submit Action |
Final submission of collected data |
postMessage, preTransformBundle, postTransformBundle |
Phase 3: Generation & Validation
# Verify no duplicate Type/SubType/Language exists
sf data query -q "SELECT Id,Name,Type,SubType,Language,IsActive,VersionNumber FROM OmniProcess WHERE Type='<Type>' AND SubType='<SubType>' AND Language='<Language>' AND OmniProcessType='OmniScript'" -o <org>
Build the OmniScript:
- Create the OmniProcess record with Type, SubType, Language, and OmniProcessType='OmniScript'
- Create OmniProcessElement child records for each Step (Level=0)
- Create OmniProcessElement child records for each element within Steps (Level=1+, ordered by Order field)
- Configure PropertySetConfig JSON for each element
- Wire action elements to their Integration Procedures / DataRaptors
Validation (STRICT MODE):
- BLOCK: Missing Type/SubType/Language, circular OmniScript embedding, broken IP/DataRaptor references, missing required PropertySetConfig fields
- WARN: Steps with no elements, input elements without validation, missing error handling on actions, unused data paths, deeply nested elements (>4 levels)
Validation Report Format (6-Category Scoring 0-120):
Score: 102/120 ---- Very Good
-- Design & Structure: 22/25 (88%)
-- Data Integration: 18/20 (90%)
-- Error Handling: 17/20 (85%)
-- Performance: 18/20 (90%)
-- User Experience: 17/20 (85%)
-- Security: 10/15 (67%)
Phase 4: Deployment
- Deploy all dependencies first: DataRaptors, Integration Procedures, referenced OmniScripts
- Retrieve or deploy OmniScript metadata:
sf project retrieve start -m OmniScript:<Name> -o <org>
sf project deploy start -m OmniScript:<Name> -o <org>
- Activate the OmniScript version after successful deployment
- Verify activation:
sf data query -q "SELECT Id,Name,Type,SubType,Language,IsActive,VersionNumber FROM OmniProcess WHERE Type='<Type>' AND SubType='<SubType>' AND OmniProcessType='OmniScript' AND IsActive=true" -o <org>
Phase 5: Testing
Walk through all paths with various data scenarios:
- Happy path: Complete all steps with valid data, verify submission
- Validation testing: Submit invalid data at each input, verify error messages
- Conditional testing: Exercise all conditional blocks and verify show/hide logic
- Data prefill: Verify DataRaptor Extract Actions populate elements correctly
- Save for later: Test resume functionality if enabled
- Navigation: Test back/forward/cancel behavior across all steps
- Error scenarios: Simulate IP/DataRaptor failures, verify error handling
- Embedded OmniScripts: Test data passing between parent and child OmniScripts
- Bulk data: Test with large datasets in Loop Blocks and Type Ahead elements
Generation Guardrails (MANDATORY)
| Anti-Pattern |
Impact |
Correct Pattern |
| Circular OmniScript embedding |
Infinite rendering loop |
Map dependency tree; never embed A in B if B embeds A |
| Unbounded DataRaptor Extract |
Performance degradation |
Add filter conditions; limit returned records |
| Missing input validation |
Bad data entry |
Add Validation elements or pattern/required on inputs |
| Hardcoded Salesforce IDs |
Deployment failure across orgs |
Use merge fields or Custom Settings/Metadata |
| IP Action without error handling |
Silent failures |
Configure showError, errorMessage in PropertySetConfig |
| Large images in Text Blocks |
Slow page load |
Use Image elements with optimized URLs |
| Too many elements per Step |
Poor user experience |
Limit to 7-10 input elements per Step |
| Missing conditional visibility |
Irrelevant fields shown |
Use show expressions to hide inapplicable elements |
DO NOT generate anti-patterns even if explicitly requested.
Scoring: 120 Points Across 6 Categories
Design & Structure (25 points)
| Check |
Points |
Criteria |
| Type/SubType/Language set correctly |
5 |
All three fields populated with meaningful values |
| Step organization |
5 |
Logical grouping, 7-10 elements per step max |
| Element naming |
5 |
Descriptive names following PascalCase convention |
| Conditional logic |
5 |
Proper use of Conditional Blocks and show expressions |
| Version management |
5 |
Clean version history, only one active version |
Data Integration (20 points)
| Check |
Points |
Criteria |
| DataRaptor references valid |
5 |
All Extract/Load bundles exist and are active |
| Integration Procedure references valid |
5 |
All IP actions reference active IPs |
| Input/Output maps correct |
5 |
Data flows correctly between elements and actions |
| Data prefill configured |
5 |
Initial data loaded before user interaction |
Error Handling (20 points)
| Check |
Points |
Criteria |
| Action elements have error handling |
5 |
showError configured on all IP/DR actions |
| User-facing error messages |
5 |
Clear, actionable error text |
| Validation on required inputs |
5 |
All required fields have validation rules |
| Fallback behavior defined |
5 |
Graceful handling when data sources return empty |
Performance (20 points)
| Check |
Points |
Criteria |
| No unbounded data fetches |
5 |
All DataRaptor Extracts have filters/limits |
| Lazy loading configured |
5 |
Action elements fire on step entry, not OmniScript load |
| Element count per Step reasonable |
5 |
No Step with >15 elements |
| Conditional rendering used |
5 |
Elements hidden when not applicable (not just invisible) |
User Experience (20 points)
| Check |
Points |
Criteria |
| Logical step flow |
5 |
Steps follow natural task progression |
| Input labels and help text |
5 |
All inputs have clear labels and contextual help |
| Navigation controls |
5 |
Back, Next, Cancel, Save for Later configured appropriately |
| Responsive layout |
5 |
Elements configured for mobile and desktop breakpoints |
Security (15 points)
| Check |
Points |
Criteria |
| No sensitive data in client-side JSON |
5 |
Passwords, SSNs, tokens kept server-side |
| IP actions use server-side processing |
5 |
Sensitive logic in Integration Procedures, not client OmniScript |
| Field-level access respected |
5 |
Data access matches user profile/permission set |
CLI Commands
# List active OmniScripts
sf data query -q "SELECT Id,Name,Type,SubType,Language,IsActive,VersionNumber FROM OmniProcess WHERE IsActive=true AND OmniProcessType='OmniScript'" -o <org>
# Query elements for a specific OmniScript
sf data query -q "SELECT Id,Name,ElementType,PropertySetConfig,Level,Order FROM OmniProcessElement WHERE OmniProcessId='<id>' ORDER BY Level,Order" -o <org>
# Retrieve OmniScript metadata
sf project retrieve start -m OmniScript:<Name> -o <org>
# Deploy OmniScript metadata
sf project deploy start -m OmniScript:<Name> -o <org>
# Check OmniScript versions
sf data query -q "SELECT Id,VersionNumber,IsActive,LastModifiedDate FROM OmniProcess WHERE Type='<Type>' AND SubType='<SubType>' AND OmniProcessType='OmniScript' ORDER BY VersionNumber DESC" -o <org>
Cross-Skill Integration
| From Skill |
To sf-industry-commoncore-omniscript |
When |
| sf-industry-commoncore-omnistudio-analyze |
-> sf-industry-commoncore-omniscript |
"Analyze dependencies before building OmniScript" |
| sf-industry-commoncore-datamapper |
-> sf-industry-commoncore-omniscript |
"DataRaptor ready, build the OmniScript that uses it" |
| sf-industry-commoncore-integration-procedure |
-> sf-industry-commoncore-omniscript |
"IP ready, wire it into the OmniScript action" |
| From sf-industry-commoncore-omniscript |
To Skill |
When |
| sf-industry-commoncore-omniscript |
-> sf-industry-commoncore-flexcard |
"Build FlexCard that launches this OmniScript" |
| sf-industry-commoncore-omniscript |
-> sf-deploy |
"Deploy OmniScript to target org" |
| sf-industry-commoncore-omniscript |
-> sf-industry-commoncore-omnistudio-analyze |
"Map full dependency tree before deployment" |
| sf-industry-commoncore-omniscript |
-> sf-industry-commoncore-integration-procedure |
"Need a new IP for this OmniScript action" |
| sf-industry-commoncore-omniscript |
-> sf-industry-commoncore-datamapper |
"Need a DataRaptor for data prefill" |
Edge Cases
| Scenario |
Solution |
| Multi-language OmniScript |
Create separate versions per Language with shared Type/SubType. Use translation workbench for labels |
| Embedded OmniScript data passing |
Map parent data JSON keys to child OmniScript input via prefillJSON. Test data round-trip |
| Large Loop Block datasets |
Paginate or limit DataRaptor results. Consider server-side filtering in IP |
| OmniScript in FlexCard flyout |
Ensure FlexCard passes required context data. Test flyout sizing |
| Community/Experience Cloud deployment |
Verify OmniScript component is available in Experience Builder. Check guest user permissions |
| Save & Resume (Save for Later) |
Configure saveNameTemplate, saveExpireInDays. Test resume with partial data |
| Versioning conflicts |
Deactivate old version before activating new. Never have two active versions for same triplet |
| Custom Lightning Web Components in OmniScript |
Register LWC as OmniScript-compatible. Follow omniscript-lwc namespace conventions |
Debug: OmniScript not rendering -> check activation status + element hierarchy | Data not prefilling -> verify DataRaptor Extract output mapping + JSON path | IP action failing -> check IP independently first + verify input map | Steps not showing -> review conditional visibility expressions
Notes
Dependencies (required): sf-industry-commoncore-datamapper, sf-industry-commoncore-integration-procedure | Dependencies (optional): sf-deploy, sf-industry-commoncore-flexcard, sf-industry-commoncore-omnistudio-analyze | API: 66.0 | Mode: Strict (warnings block) | Scoring: Block deployment if score < 67 | Reference docs: See references/ for element types and best practices
Creating OmniScripts programmatically: Use REST API (sf api request rest --method POST --body @file.json). Required fields: Name, Type, SubType, Language, VersionNumber. OmniScripts default to IsIntegrationProcedure=false (do NOT set OmniProcessType — it is computed). The sf data create record --values flag cannot handle JSON textarea fields like PropertySetConfig. Create child OmniProcessElement records via REST API for each Step and element.
License
MIT License.
Copyright (c) 2026 David Ryan (weytani)
1---2name: sf-industry-commoncore-omniscript3description: OmniStudio OmniScript creation and validation with 120-point scoring. Use when building guided digital experiences, multi-step forms, or interactive processes that orchestrate Integration Procedures and Data Mappers. TRIGGER when: user creates OmniScripts, designs step flows, configures element types, or reviews existing OmniScript configurations. DO NOT TRIGGER when: building FlexCards (use sf-industry-commoncore-flexcard), creating Integration Procedures directly (use sf-industry-commoncore-integration-procedure), or analyzing dependencies (use sf-industry-commoncore-omnistudio-analyze).4license: MIT5---67# sf-industry-commoncore-omniscript: OmniStudio OmniScript Creation and Validation89Expert OmniStudio OmniScript builder for declarative, step-based guided digital experiences. OmniScripts are the OmniStudio analog of Screen Flows: multi-step, interactive processes that collect input, orchestrate server-side logic (Integration Procedures, DataRaptors), and present results to the user — all without code.1011## Quick Reference1213**Scoring**: 120 points across 6 categories. **Thresholds**: ✅ 90+ (Deploy) | ⚠️ 67-89 (Review) | ❌ <67 (Block - fix required)1415---1617## Core Responsibilities18191. **OmniScript Generation**: Create well-structured OmniScripts from requirements, selecting appropriate element types for each step202. **Element Design**: Configure PropertySetConfig JSON for each element with correct data binding, validation, and conditional logic213. **Dependency Analysis**: Map all references to Integration Procedures, DataRaptors, and embedded OmniScripts before deployment224. **Data Flow Analysis**: Trace data through the OmniScript JSON structure — from prefill through user input to final save actions2324---2526## CRITICAL: Orchestration Order2728**sf-industry-commoncore-omnistudio-analyze → sf-industry-commoncore-datamapper → sf-industry-commoncore-integration-procedure → sf-industry-commoncore-omniscript → sf-industry-commoncore-flexcard** (you are here: sf-industry-commoncore-omniscript)2930OmniScripts consume Integration Procedures and DataRaptors. Build those FIRST. FlexCards may launch OmniScripts — build FlexCards AFTER. Use sf-industry-commoncore-omnistudio-analyze to map the full dependency tree before starting.3132---3334## Key Insights3536| Insight | Details |37|---------|---------|38| **Type/SubType/Language triplet** | Uniquely identifies an OmniScript. All three values are required and form the composite key. Example: Type=`ServiceRequest`, SubType=`NewCase`, Language=`English` |39| **PropertySetConfig** | JSON blob containing all element configuration — layout, data binding, validation rules, conditional visibility. This is where the real logic lives |40| **Core namespace** | OmniProcess with `IsIntegrationProcedure = false` (equivalently `OmniProcessType='OmniScript'`). Elements are child OmniProcessElement records |41| **Element hierarchy** | Elements use Level/Order fields for tree structure. Level 0 = Steps, Level 1+ = elements within steps. Order determines sequence within a level |42| **Version management** | Multiple versions can exist; only one can be active per Type/SubType/Language triplet. Activate via the `IsActive` field |43| **Data JSON** | OmniScripts pass a single JSON data structure through all steps. Elements read from and write to this shared JSON via merge field syntax |4445---4647## Workflow Design (5-Phase Pattern)4849### Phase 1: Requirements Gathering5051**Before building, evaluate alternatives**: OmniScripts are best for complex, multi-step guided processes. For simple single-screen data entry, consider Screen Flows. For data display without interaction, consider FlexCards.5253**Ask the user** to gather:54- **Type**: The process category (e.g., `ServiceRequest`, `Enrollment`, `ClaimSubmission`)55- **SubType**: The specific variation (e.g., `NewCase`, `UpdateAddress`, `FileAppeal`)56- **Language**: Typically `English` unless multi-language support is required57- **Purpose**: What business process this OmniScript guides the user through58- **Target org**: Org alias for deployment59- **Data sources**: Which objects/APIs need to be queried or updated6061**Then**: Check existing OmniScripts to avoid duplication, identify reusable Integration Procedures or DataRaptors, and map the dependency chain.6263### Phase 2: Design & Element Selection6465Design each step and select element types appropriate to the interaction pattern.6667#### Container Elements6869| Element Type | Purpose | Key Config |70|-------------|---------|------------|71| **Step** | Top-level container for a group of UI elements; each Step is a page in the wizard | `chartLabel`, `knowledgeOptions`, `show` (conditional visibility) |72| **Conditional Block** | Show/hide a group of elements based on conditions | `conditionType`, `show` expression |73| **Loop Block** | Iterate over a data list and render elements for each item | `loopData` (JSON path to array) |74| **Edit Block** | Inline editing container for tabular data | `editFields`, `dataSource` |7576#### Input Elements7778| Element Type | Purpose | Key Config |79|-------------|---------|------------|80| **Text** | Single-line text input | `label`, `placeholder`, `pattern` (regex validation) |81| **Text Area** | Multi-line text input | `label`, `maxLength`, `rows` |82| **Number** | Numeric input with optional formatting | `label`, `min`, `max`, `step`, `format` |83| **Date** | Date picker | `label`, `dateFormat`, `minDate`, `maxDate` |84| **Date/Time** | Date and time picker | `label`, `dateFormat`, `timeFormat` |85| **Checkbox** | Boolean toggle | `label`, `defaultValue` |86| **Radio** | Radio button group for single selection | `label`, `options` (static or data-driven) |87| **Select** | Dropdown selection | `label`, `options`, `optionSource` (static/data) |88| **Multi-select** | Multiple item selection | `label`, `options`, `maxSelections` |89| **Type Ahead** | Search/autocomplete input | `label`, `dataSource`, `searchField`, `minCharacters` |90| **Signature** | Signature capture pad | `label`, `penColor`, `backgroundColor` |91| **File** | File upload | `label`, `maxFileSize`, `allowedExtensions` |92| **Currency** | Currency input with locale formatting | `label`, `currencyCode`, `min`, `max` |93| **Email** | Email input with format validation | `label`, `placeholder` |94| **Telephone** | Phone number input with masking | `label`, `mask`, `placeholder` |95| **URL** | URL input with format validation | `label`, `placeholder` |96| **Password** | Masked text input | `label`, `minLength` |97| **Range** | Slider input | `label`, `min`, `max`, `step` |98| **Time** | Time picker | `label`, `timeFormat` |99100#### Display Elements101102| Element Type | Purpose | Key Config |103|-------------|---------|------------|104| **Text Block** | Static content display (HTML supported) | `textContent`, `HTMLTemplateId` |105| **Headline** | Section heading | `text`, `level` (h1-h6) |106| **Aggregate** | Calculated summary display | `aggregateExpression`, `format` |107| **Disclosure** | Expandable/collapsible content | `label`, `defaultExpanded` |108| **Image** | Image display | `imageURL`, `altText` |109| **Chart** | Data visualization | `chartType`, `dataSource` |110111#### Action Elements112113| Element Type | Purpose | Key Config |114|-------------|---------|------------|115| **DataRaptor Extract Action** | Pull data from Salesforce | `bundle`, `inputMap`, `outputMap` |116| **DataRaptor Load Action** | Push data to Salesforce | `bundle`, `inputMap` |117| **Integration Procedure Action** | Call server-side Integration Procedure | `ipMethod` (Type_SubType), `inputMap`, `outputMap`, `remoteOptions` |118| **Remote Action** | Call Apex @RemoteAction or REST | `remoteClass`, `remoteMethod`, `inputMap` |119| **Navigate Action** | Page navigation or redirection | `targetType`, `targetId`, `URL` |120| **DocuSign Envelope Action** | Trigger DocuSign envelope | `templateId`, `recipientMap` |121| **Email Action** | Send email | `emailTemplateId`, `recipientMap` |122123#### Logic Elements124125| Element Type | Purpose | Key Config |126|-------------|---------|------------|127| **Set Values** | Variable assignment and data transformation | `elementValueMap` (key-value pairs) |128| **Validation** | Input validation rules with custom messages | `validationFormula`, `errorMessage` |129| **Formula** | Calculate values using formula expressions | `expression`, `dataType` |130| **Submit Action** | Final submission of collected data | `postMessage`, `preTransformBundle`, `postTransformBundle` |131132### Phase 3: Generation & Validation133134```bash135# Verify no duplicate Type/SubType/Language exists136sf data query -q "SELECT Id,Name,Type,SubType,Language,IsActive,VersionNumber FROM OmniProcess WHERE Type='<Type>' AND SubType='<SubType>' AND Language='<Language>' AND OmniProcessType='OmniScript'" -o <org>137```138139**Build the OmniScript**:1401. Create the OmniProcess record with Type, SubType, Language, and OmniProcessType='OmniScript'1412. Create OmniProcessElement child records for each Step (Level=0)1423. Create OmniProcessElement child records for each element within Steps (Level=1+, ordered by Order field)1434. Configure PropertySetConfig JSON for each element1445. Wire action elements to their Integration Procedures / DataRaptors145146**Validation (STRICT MODE)**:147- **BLOCK**: Missing Type/SubType/Language, circular OmniScript embedding, broken IP/DataRaptor references, missing required PropertySetConfig fields148- **WARN**: Steps with no elements, input elements without validation, missing error handling on actions, unused data paths, deeply nested elements (>4 levels)149150**Validation Report Format** (6-Category Scoring 0-120):151```152Score: 102/120 ---- Very Good153-- Design & Structure: 22/25 (88%)154-- Data Integration: 18/20 (90%)155-- Error Handling: 17/20 (85%)156-- Performance: 18/20 (90%)157-- User Experience: 17/20 (85%)158-- Security: 10/15 (67%)159```160161### Phase 4: Deployment1621631. Deploy all dependencies first: DataRaptors, Integration Procedures, referenced OmniScripts1642. Retrieve or deploy OmniScript metadata:165 ```bash166 sf project retrieve start -m OmniScript:<Name> -o <org>167 sf project deploy start -m OmniScript:<Name> -o <org>168 ```1693. Activate the OmniScript version after successful deployment1704. Verify activation:171 ```bash172 sf data query -q "SELECT Id,Name,Type,SubType,Language,IsActive,VersionNumber FROM OmniProcess WHERE Type='<Type>' AND SubType='<SubType>' AND OmniProcessType='OmniScript' AND IsActive=true" -o <org>173 ```174175### Phase 5: Testing176177Walk through all paths with various data scenarios:178- **Happy path**: Complete all steps with valid data, verify submission179- **Validation testing**: Submit invalid data at each input, verify error messages180- **Conditional testing**: Exercise all conditional blocks and verify show/hide logic181- **Data prefill**: Verify DataRaptor Extract Actions populate elements correctly182- **Save for later**: Test resume functionality if enabled183- **Navigation**: Test back/forward/cancel behavior across all steps184- **Error scenarios**: Simulate IP/DataRaptor failures, verify error handling185- **Embedded OmniScripts**: Test data passing between parent and child OmniScripts186- **Bulk data**: Test with large datasets in Loop Blocks and Type Ahead elements187188---189190## Generation Guardrails (MANDATORY)191192| Anti-Pattern | Impact | Correct Pattern |193|--------------|--------|-----------------|194| Circular OmniScript embedding | **Infinite rendering loop** | Map dependency tree; never embed A in B if B embeds A |195| Unbounded DataRaptor Extract | **Performance degradation** | Add filter conditions; limit returned records |196| Missing input validation | **Bad data entry** | Add Validation elements or `pattern`/`required` on inputs |197| Hardcoded Salesforce IDs | **Deployment failure across orgs** | Use merge fields or Custom Settings/Metadata |198| IP Action without error handling | **Silent failures** | Configure `showError`, `errorMessage` in PropertySetConfig |199| Large images in Text Blocks | **Slow page load** | Use Image elements with optimized URLs |200| Too many elements per Step | **Poor user experience** | Limit to 7-10 input elements per Step |201| Missing conditional visibility | **Irrelevant fields shown** | Use `show` expressions to hide inapplicable elements |202203**DO NOT generate anti-patterns even if explicitly requested.**204205---206207## Scoring: 120 Points Across 6 Categories208209### Design & Structure (25 points)210211| Check | Points | Criteria |212|-------|--------|----------|213| Type/SubType/Language set correctly | 5 | All three fields populated with meaningful values |214| Step organization | 5 | Logical grouping, 7-10 elements per step max |215| Element naming | 5 | Descriptive names following `PascalCase` convention |216| Conditional logic | 5 | Proper use of Conditional Blocks and `show` expressions |217| Version management | 5 | Clean version history, only one active version |218219### Data Integration (20 points)220221| Check | Points | Criteria |222|-------|--------|----------|223| DataRaptor references valid | 5 | All Extract/Load bundles exist and are active |224| Integration Procedure references valid | 5 | All IP actions reference active IPs |225| Input/Output maps correct | 5 | Data flows correctly between elements and actions |226| Data prefill configured | 5 | Initial data loaded before user interaction |227228### Error Handling (20 points)229230| Check | Points | Criteria |231|-------|--------|----------|232| Action elements have error handling | 5 | `showError` configured on all IP/DR actions |233| User-facing error messages | 5 | Clear, actionable error text |234| Validation on required inputs | 5 | All required fields have validation rules |235| Fallback behavior defined | 5 | Graceful handling when data sources return empty |236237### Performance (20 points)238239| Check | Points | Criteria |240|-------|--------|----------|241| No unbounded data fetches | 5 | All DataRaptor Extracts have filters/limits |242| Lazy loading configured | 5 | Action elements fire on step entry, not OmniScript load |243| Element count per Step reasonable | 5 | No Step with >15 elements |244| Conditional rendering used | 5 | Elements hidden when not applicable (not just invisible) |245246### User Experience (20 points)247248| Check | Points | Criteria |249|-------|--------|----------|250| Logical step flow | 5 | Steps follow natural task progression |251| Input labels and help text | 5 | All inputs have clear labels and contextual help |252| Navigation controls | 5 | Back, Next, Cancel, Save for Later configured appropriately |253| Responsive layout | 5 | Elements configured for mobile and desktop breakpoints |254255### Security (15 points)256257| Check | Points | Criteria |258|-------|--------|----------|259| No sensitive data in client-side JSON | 5 | Passwords, SSNs, tokens kept server-side |260| IP actions use server-side processing | 5 | Sensitive logic in Integration Procedures, not client OmniScript |261| Field-level access respected | 5 | Data access matches user profile/permission set |262263---264265## CLI Commands266267```bash268# List active OmniScripts269sf data query -q "SELECT Id,Name,Type,SubType,Language,IsActive,VersionNumber FROM OmniProcess WHERE IsActive=true AND OmniProcessType='OmniScript'" -o <org>270271# Query elements for a specific OmniScript272sf data query -q "SELECT Id,Name,ElementType,PropertySetConfig,Level,Order FROM OmniProcessElement WHERE OmniProcessId='<id>' ORDER BY Level,Order" -o <org>273274# Retrieve OmniScript metadata275sf project retrieve start -m OmniScript:<Name> -o <org>276277# Deploy OmniScript metadata278sf project deploy start -m OmniScript:<Name> -o <org>279280# Check OmniScript versions281sf data query -q "SELECT Id,VersionNumber,IsActive,LastModifiedDate FROM OmniProcess WHERE Type='<Type>' AND SubType='<SubType>' AND OmniProcessType='OmniScript' ORDER BY VersionNumber DESC" -o <org>282```283284---285286## Cross-Skill Integration287288| From Skill | To sf-industry-commoncore-omniscript | When |289|------------|------------------|------|290| sf-industry-commoncore-omnistudio-analyze | -> sf-industry-commoncore-omniscript | "Analyze dependencies before building OmniScript" |291| sf-industry-commoncore-datamapper | -> sf-industry-commoncore-omniscript | "DataRaptor ready, build the OmniScript that uses it" |292| sf-industry-commoncore-integration-procedure | -> sf-industry-commoncore-omniscript | "IP ready, wire it into the OmniScript action" |293294| From sf-industry-commoncore-omniscript | To Skill | When |295|--------------------|----------|------|296| sf-industry-commoncore-omniscript | -> sf-industry-commoncore-flexcard | "Build FlexCard that launches this OmniScript" |297| sf-industry-commoncore-omniscript | -> sf-deploy | "Deploy OmniScript to target org" |298| sf-industry-commoncore-omniscript | -> sf-industry-commoncore-omnistudio-analyze | "Map full dependency tree before deployment" |299| sf-industry-commoncore-omniscript | -> sf-industry-commoncore-integration-procedure | "Need a new IP for this OmniScript action" |300| sf-industry-commoncore-omniscript | -> sf-industry-commoncore-datamapper | "Need a DataRaptor for data prefill" |301302---303304## Edge Cases305306| Scenario | Solution |307|----------|----------|308| Multi-language OmniScript | Create separate versions per Language with shared Type/SubType. Use translation workbench for labels |309| Embedded OmniScript data passing | Map parent data JSON keys to child OmniScript input via `prefillJSON`. Test data round-trip |310| Large Loop Block datasets | Paginate or limit DataRaptor results. Consider server-side filtering in IP |311| OmniScript in FlexCard flyout | Ensure FlexCard passes required context data. Test flyout sizing |312| Community/Experience Cloud deployment | Verify OmniScript component is available in Experience Builder. Check guest user permissions |313| Save & Resume (Save for Later) | Configure `saveNameTemplate`, `saveExpireInDays`. Test resume with partial data |314| Versioning conflicts | Deactivate old version before activating new. Never have two active versions for same triplet |315| Custom Lightning Web Components in OmniScript | Register LWC as OmniScript-compatible. Follow `omniscript-lwc` namespace conventions |316317**Debug**: OmniScript not rendering -> check activation status + element hierarchy | Data not prefilling -> verify DataRaptor Extract output mapping + JSON path | IP action failing -> check IP independently first + verify input map | Steps not showing -> review conditional visibility expressions318319---320321## Notes322323**Dependencies** (required): sf-industry-commoncore-datamapper, sf-industry-commoncore-integration-procedure | **Dependencies** (optional): sf-deploy, sf-industry-commoncore-flexcard, sf-industry-commoncore-omnistudio-analyze | **API**: 66.0 | **Mode**: Strict (warnings block) | **Scoring**: Block deployment if score < 67 | **Reference docs**: See `references/` for element types and best practices324325**Creating OmniScripts programmatically**: Use REST API (`sf api request rest --method POST --body @file.json`). Required fields: `Name`, `Type`, `SubType`, `Language`, `VersionNumber`. OmniScripts default to `IsIntegrationProcedure=false` (do NOT set `OmniProcessType` — it is computed). The `sf data create record --values` flag cannot handle JSON textarea fields like `PropertySetConfig`. Create child `OmniProcessElement` records via REST API for each Step and element.326327---328329## License330331MIT License.332Copyright (c) 2026 David Ryan (weytani)