OmniScripts
Build guided user flows with OmniStudio OmniScripts. Describe the steps and AI generates the JSON configuration.
Skill Details
Install this skill
Works with
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
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 | |
| 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 |
| 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 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 |
| 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 |
| 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 |
| 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 |
| 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 |
| 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 |
| 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 |
| 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 |
| 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) |
| 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 |
| 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 |
| 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" |
| 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)
Navigate Industries