Skip to content

MoveData ships with built-in flows that handle standard processing. These create Contacts, Opportunities, Campaigns, and their relationships. But every organisation has unique requirements — custom fields, business rules, conditional logic, and data transformations. Extension flows let you meet those requirements.

Extension flows are unmanaged Autolaunched Flows that run alongside the managed package flows at each pipeline stage. They follow the naming pattern [MoveData Extension] {Schema}: {Object} - {Stage}. For example: [MoveData Extension] Donation: Contact - Mapping. Each extension flow receives the same Record variable that the managed flow uses, adds field assignments, and returns it.

Managed flows vs extension flows

Managed flows (prefixed [MoveData]) belong to the package — never edit them. Extension flows (prefixed [MoveData Extension]) are customer-specific. These are the only flows you create or modify.

How extension flows fit into the architecture#

MoveData processes each notification through a pipeline of ordered stages. At each stage, the managed package runs its own flow first (typically at Order 5). It then runs any registered extension flows — typically at Order 6 for mapping, or Order 4 for record match extensions.

Extension flows join this pipeline through pipeline metadata registration. This is a custom metadata record that tells MoveData "run this flow at this stage, in this order." Without that registration, MoveData never calls the flow — even if it exists in the org.

Pipeline background

For background on how pipelines work, see Pipeline overview.

The core pattern: Record pass-through#

Every extension flow follows the same pattern:

  1. Receive a Record variable (a Salesforce object — Contact, Opportunity, Campaign, etc.) as input.
  2. Receive extra input variables with notification data (email, phone, amount, platform-specific fields).
  3. Null-check each input variable before using it.
  4. Assign values to fields on the Record variable.
  5. Return the modified Record as output.

No database operations needed

MoveData handles the insert or update for you. Your mapping extension flow never needs to save the record. This means no SOQL queries and no DML operations — only in-memory assignments and decisions.

Finding a relevant notification#

Before writing flow logic, you need to understand what data MoveData passes into your flow. The best way is to find a real notification from the org's integration and inspect its variables.

What is a notification key?#

MoveData tracks every event it processes as a notification. Each notification has a unique notification key — a 32-character alphanumeric string that ends with the letter N. You use this key to look up, inspect, and replay notifications.

Practical workflow#

  1. Find a recent successful notification for your platform in the Notifications tab.
  2. Pick one that matches your use case (e.g., a donation notification for donation mapping logic).
  3. Open the notification and click the Execution tab. Scroll to the relevant phase to see the variables available at that stage. Use the Variable Inspector to search for specific variables and view their values.
  4. Use these variable names and sample values to guide your flow design.

For a full guide on reading execution logs and inspecting variables, see Viewing execution logs.

Working with flow variables#

The Record variable#

The Record variable is central to every MoveData extension flow. It is a Salesforce object variable that works as both input and output:

  • Input: MoveData passes the Record in with any existing field values.
  • Output: MoveData reads back your changes and saves them.

The Salesforce object type depends on the stage and extension:

Stage NPSP object type Nonprofit Cloud object type
Account Account Account
Contact Contact Account (Person Account)
Campaign Campaign Campaign
Recurring npe03__Recurring_Donation__c GiftCommitment
Donation Opportunity GiftTransaction
Catalogue Product2 Product2
Order Opportunity Opportunity
Order Item OpportunityLineItem OpportunityLineItem

In mapping flows, you read existing field values and assign new ones to the Record. MoveData saves the Record after all mapping flows complete.

In post-upsert flows, the Record is input-only. The Record has already been saved and includes the Salesforce record ID.

Variable naming conventions#

MoveData variable names follow predictable prefixes:

Prefix Meaning Example
(none) Core pipeline variable Record, Key, Email, Phone, Amount, Status
Custom_ Platform-specific field Custom_DonorUserId, Custom_PaymentDate
Campaign_ Campaign-context variable for downstream stages Campaign_FundraiserKey, Campaign_TeamKey
Context_ Processing context flag Context_ContactType
Questions_ Custom form field from Raisely Questions_OptIn
Marketing_ UTM attribution Marketing_Source, Marketing_Campaign
Config_ Pipeline configuration Config_CampaignNameIgnoreCampaignCode
Donor Donor personal details (donation stage) DonorFirstName, DonorEmail
MailingAddress_ Address components MailingAddress_City, MailingAddress_Street

Why you must null-check all input variables#

Every MoveData input variable can be null. The external platform may not provide a phone number. The donation may not have a fee. If you assign a null variable to a Record field, you risk overwriting existing data with blank or causing a runtime error.

Critical: null-check every input variable

Every input variable must be null-checked before assignment. This is the single most important rule in MoveData extension flow development.

The standard pattern is a Decision element before each Assignment:

Decision: "Assess Phone" (Phone IsNull = false?)
  - Exists → Set Mobile Phone
  - Default → Skip to next section

Pipeline metadata registration#

Why metadata registration matters#

Every extension flow needs a matching record in the movedata__MoveData_Pipeline__mdt custom metadata type. This record tells MoveData: "At this pipeline stage, for this object, run this flow, in this order."

Registration is required

Without the pipeline metadata record, MoveData will never run your flow. The flow will exist in the org, pass all validation, and deploy — but do nothing.

How to create the pipeline metadata record#

Clone an existing managed pipeline record for your object and stage. Then make these changes:

Field Value
DeveloperName Replace the suffix with _EXT (e.g., DONATION_CONTACT_MAPPING_EXT)
Label Keep the PIPELINE_ prefix (e.g., PIPELINE_DONATION_CONTACT_MAPPING)
Handler The API name of your extension flow (e.g., MoveData_Donation_Contact_Mapping_Ext)
Order 4 for record match extensions (before managed), 6 for mapping and post-upsert extensions (after managed)
Disabled false
Type Flow

Commerce pipeline registration#

MoveData has two pipeline schemas: Donation and Commerce. Extension flows work across both — one flow serves both schemas. But each schema needs its own pipeline metadata record.

Donation record Commerce record Handler (same flow)
DONATION_CONTACT_MAPPING_EXT COMMERCE_CONTACT_MAPPING_EXT MoveData_Donation_Contact_Mapping_Ext
DONATION_DONATION_MAPPING_EXT COMMERCE_ORDER_MAPPING_EXT MoveData_Donation_Donation_Mapping_Ext
DONATION_CAMPAIGN_MAPPING_EXT COMMERCE_CAMPAIGN_MAPPING_EXT MoveData_Donation_Campaign_Mapping_Ext

Shared flows

Do not create separate Commerce extension flows. One flow serves both schemas — only the pipeline metadata records differ.

Ordering#

The Order field controls which flows run first within a stage:

Order What runs Why
4 Extension record match flow Runs before the managed flow to intercept matching
5 Managed package flow Built-in processing
6 Extension mapping / post-upsert flow Runs after managed flow to override or add to results

Fieldsets#

What fieldsets control#

Fieldsets control which Salesforce fields MoveData includes in its query when it looks up a record. If a field is missing from both the managed fieldset and the extension fieldset, MoveData does not query it. The field will appear as null on the Record variable, even if the record has data in that field.

This matters most for Decision elements. If your flow makes a decision based on a field that is not in the fieldset, the field value will be null and the decision may fail or produce incorrect results. Field assignments will still work without the fieldset entry, but it is best practice to add all fields your extension flow interacts with.

Fields used in decisions must be in the fieldset

Any field you evaluate in a Decision element must be included in the extension fieldset. Without it, MoveData does not query the field, and your decision logic receives null regardless of the actual value on the record.

How to create an extension fieldset#

Extension fieldsets follow this naming convention:

Object FieldSet API name Label
Contact MoveData_Donation_Contact_Fieldset_Ext [MoveData Extension] Donation: Contact Fieldset
Opportunity MoveData_Donation_Donation_Fieldset_Ext [MoveData Extension] Opportunity Fieldset
Campaign MoveData_Donation_Campaign_Fieldset_Ext [MoveData Extension] Donation: Campaign Fieldset
Account MoveData_Donation_Account_Fieldset_Ext [MoveData Extension] Donation: Account Fieldset

Fieldset pipeline registration#

Like extension flows, fieldsets need pipeline metadata records. Each fieldset needs records for both the Donation and Commerce pipelines.

Field Value
DeveloperName e.g., DONATION_CONTACT_FIELDSET_EXT (and COMMERCE_CONTACT_FIELDSET_EXT for Commerce)
Handler The API name of your fieldset (e.g., MoveData_Donation_Contact_Fieldset_Ext)
Type Fieldset

Fieldset Type

The key difference from flow pipeline records: set Type to Fieldset instead of Flow.

Testing by reprocessing notifications#

How to test your extension flow#

Once you have built your extension flow and deployed it to your sandbox, you can test it by reprocessing an existing notification.

  1. Open the Notifications tab in the MoveData app.
  2. Find the notification you used to inspect variables earlier.
  3. Open the notification and click Reprocess. This sends the notification back through the MoveData processing pipeline. Any changes you have made in your Salesforce flows will run against it.
  4. Once reprocessing completes, open the Execution tab to review the execution log. Check that your extension flow ran and that the field values were set as expected.
  5. Open the Salesforce record itself (Contact, Opportunity, Campaign, etc.) to confirm the changes appear on the record.

What to check#

  • Your extension flow appears in the execution log at the correct phase.
  • The Record fields were set to the expected values.
  • No errors occurred during processing.
  • The Salesforce record reflects the changes you made in your flow.

Best practices#

Always null-check input variables#

Every MoveData input variable is optional. Assigning a null variable to a Record field overwrites existing data with blank. Always wrap assignments in a null-check Decision.

One flow per schema/object/stage#

Extension flows are shared. There is one flow per schema/object/stage combination. Add multiple requirements to the same flow as separate branches.

Keep mapping flows lightweight#

Mapping flows should not contain Get Records, Create/Update/Delete Records, or callouts. Use only Assignments, Decisions, Formulas, and (when needed) Apex action calls. The Record variable is modified in-place and returned — no database operations needed. Keeping mapping flows lightweight helps you stay within Salesforce governor limits.

Verify picklist values before deployment#

Any hardcoded picklist value in the flow (e.g., LeadSource = "JustGiving") must already exist on the field in the target org. Deploying a flow that assigns a missing picklist value causes runtime errors.

Ask MoveData AI
Ask about setup, configuration, or troubleshooting
How can I help you with MoveData today?