Create a Case or a Lead from a marketing form in Customer Insights - Journeys
So I will confess I have been sneakily doing this for a while but the method used to be somewhat unethical to interrupt the form submission before it was processed into a Lead. But now I can retire my sneaky hack and instead use the new(ish) form settings functionality which allows you to choose whether to create a lead/lead, and also whether to match or not, and custom unmapped fields which makes it easy to create fields for the form which do not specifically map to a lead or contact.
Why would you want to use a marketing form in Customer Insights - Journeys to create a Case?
Many websites have a generic ‘contact us’ form on their website which could serve a variety of purposes, some of these may be lead such as enquiries about products or a request for a quote. But it could also be something better handle by the customer service teams such as a problem with an purchase, feedback or complaints. These are definitely not leads but often come in via the same form.
Set up the form in Customer Insights - Journeys
First we need to set up a form which will:
Capture the form submission
Match to any existing lead or contact in the system based on your defined form matching strategy
Not create a new lead or contact
1) Set up a marketing form which uses the audience ‘Lead & Contact’, add all your fields you need for the contact form.
2) Add an ‘Option Set’ custom field to the form
If you can’t see the section for ‘Fields’ to add the option set in (2) you need to make sure you form is in ‘Draft’, and you have enabled the feature switch for Custom unmapped fields
3) Update the Logical field name to something meaningful that we can use later in out automation rules, for this example i will be using ‘ContactUsEnquiryType‘
4) Add your options, and assign a value to them. You can either use an integer value that aligns to an existing option set, or text which is meaningful to the option selected
5) Make the field required
This is how I assigned the value to my option sets on the form, based on the integer values of the choice columns in Dynamics 365 for Lead/Case
6) Update the lead duplicate rules to ‘Use a rule to match an existing lead’ and select any lead matching rule that you want to use here
7) Update rule to skip updating and or creating leads
8) Update the contact duplicate rules to ‘Use a rule to match an existing contact’ and select any contact matching rule that you want to use here
9) Update rule to skip updating and or creating contacts
Publish your form and check you can submit with no issues, and the expected behaviour of only matching existing leads/contacts happens, without any updates being made. Your form is ready, now we need to automate the lead/case creation.
Convert the form submission into a Lead or a Case with Power Automate
Now we have the data captured, we need to trigger a flow to handle the decision on creating a case or lead, and doing a bit of magic to tie the loose ends together from the unmatched form submission. Firstly, we need to create a summary of the form submission that’s in an easy to use JSON format, some instruction and bonus summary for the timeline included here.
Create an ‘Automated’ Parent Flow
Trigger a flow when a form is submitted
When the form is submitted, we can start processing, this is the parent flow
Dataverse: When a row is added, modified or deleted
Change type: Added or modified
Table name: Form Submissions (msdynmkt_marketingformsubmission)
Select columns: statuscode
Filter rows: statuscode eq 575440002
Generate the form submission summary
Call the child flow you set up as per my previous blog post to make sure the summary JSON is ready to process.
Check for the unmapped option set
Filter the field submissions to check if the form submitted contains the special instructions for creating a case or not. Use the name that you allocated to the ‘Logical field name’ on the form.
Dataverse: List rows - FieldSubmissionContactUsEnquiryType
Table name: Field Submissions (msdynmkt_marketingfieldsubmissions)
Select columns: msdynmkt_marketingfieldsubmissionid,msdynmkt_localizedfieldvalue
Filter rows: (msdynmkt_name eq 'ContactUsEnquiryType') and msdynmkt_fieldvalue ne null and _msdynmkt_marketingformsubmissionid_value eq '@{triggerOutputs()?['body/msdynmkt_marketingformsubmissionid']}'
Row count: 1
Unmapped option set response found?
First check if the list rows action has returned any data
Control: Condition - Create Lead or Case
empty(body('FieldSubmissionContactUsEnquiryType')?['value'])
is equal to
@false
If we find the field submission, that means we need to kick in our Lead or Case creation flow. In the yes branch we will call the child flow, but first we need to go an create it!
Create an ‘Instant’ Child Flow
https://make.powerapps.com/environments/cfb427c5-4603-e940-b27a-71afcade7808/solutions/fb09052f-f51c-f011-998a-000d3a1db2ab/objects/cloudflows/a0b47ef3-f81c-f011-9989-7ced8d17a307/view
Just for context
This is a reminder of how I set up the options et on the form, and how the number values assigned to the choice will determine if its a lead or a case.
Leads are generated for values 0, 1 or 2. Otherwise it’s a case.
Manually trigger a flow
Trigger the flow with ‘Flow button for mobile’. Add one text input:
FormSubmissionGUID
Get the form submission data
Retrieve all the data you need to decide what records need to be created or updated.
Dataverse: Get a row by ID - GetFormSubmissionExpand
Table Name: Form Submissions
Row ID: triggerBody()['text']
Select columns: msdynmkt_marketingformsubmissionid,_msdynmkt_createdentity_value,amey_summaryjson
Expand Query: msdynmkt_createdentity($select=msdynmkt_createdentitylinkid,msdynmkt_targetentityid,msdynmkt_targetentity,_msdynmkt_targetlead_value,_msdynmkt_targetcontact_value),msdynmkt_marketingformid($select=msdynmkt_name,msdynmkt_marketingformid)
Format the Form Submission JSON
This is using the JSON summary you created earlier, and telling the flow that it is indeed JSON, so you can select items form it later.
Data Operations: Compose - FormSubmissionJSON
Inputs: json(outputs('GetFormSubmissionExpand')?['body/amey_summaryjson'])
Get the Enquiry Type value
Store the Enquiry Type integer value in a compose action, for easier reuse and referencing later in the flow.
Data Operations: Compose - ContactUsEnquiryTypeResponse
Inputs: int(coalesce(outputs('FormSubmissionJSON')?['ContactUsEnquiryType'],-1))
Check the Enquiry Type is valid
Adding in a check point here, as although we checked in the parent flow, this child flow could be called from anywhere so checking we have a valid enquiry type means the flow can handle errors more gracefully.
Control: Condition - Action Required
outputs('ContactUsEnquiryTypeResponse')
is greater that
-1
If No - Cancel
PowerApps: Respond to a PowerApp or flow
No inputs
Control: Terminate - Cancel
Status: Cancelled
Does a Contact need to be created?
If the Enquiry Type selected was ‘Existing order(s)’ (13) or ‘Warranties’ (14) or ‘Feedback’ (15), and there was no matched Contact found as per form matching rules, then a Contact needs to be created.
Control: Condition - Case Contact Creation Required
outputs('ContactUsEnquiryTypeResponse')
is greater than
2
AND
outputs('GetFormSubmissionExpand')?['body/msdynmkt_createdentity/_msdynmkt_targetcontact_value']
is equal to
null
Create a Contact using Form Submission Data
Since no matching Contact was found, we need to use the submitted form data to create one. Make sure you link it to the Source Form and define any ownership and additional defaults you might need for Contact creation.
Dataverse: Add a new row - CreateContact
Table name: Contacts
First Name: outputs('FormSubmissionJSON')?['First Name']
Last Name: outputs('FormSubmissionJSON')?['Last Name']
Email: outputs('FormSubmissionJSON')?['Email']
Source form: msdynmkt_marketingforms/@{outputs('GetFormSubmissionExpand')?['body/msdynmkt_marketingformid/msdynmkt_marketingformid']}
Update the ‘Linked Record’ with the new Contact
Using the lovely ‘Upsert’ action here because the form submission linked record it may or may not exist depending on if any matches were found during the submission. The Linked Record is an intersect table between the form submission and the associated row (Lead or Contact or something else).
Dataverse: Upsert a row - UpsertLinkedRecordContact
Table name: Created linked entity
Row ID: coalesce(outputs('GetFormSubmissionExpand')?['body/_msdynmkt_createdentity_value'], guid())
Name: outputs('CreateContact')?['body/fullname']
Contact record: contacts/@{outputs('CreateContact')?['body/contactid']}
For context, this is the linked record on the form submission
Does a Case need to be created?
Next we need to evaluate the Enquiry type response to decide whether to create a Lead or a Contact. If the Enquiry Type selected was ‘Existing order(s)’ (13) or ‘Warranties’ (14) or ‘Feedback’ (15), then a Case needs to be created. Add this action below the previous the condition, outside of the Yes/No branches (see screenshot at the end for full flow layout).
Control: Condition - Case
outputs('ContactUsEnquiryTypeResponse')
is greater than
2
Create a Case using Form Submission Data
Use the submitted form data to create a new Case. Make sure you link the Case to the relevant Contact and define any ownership and additional defaults you might need for Case creation and routing.
Dataverse: Add a new row - CreateCase
Table name: Cases
Case Title: outputs('GetFormSubmissionExpand')?['body/msdynmkt_marketingformid/msdynmkt_name']
Case Type: outputs('ContactUsEnquiryTypeResponse')
Customer (Contacts): contacts/@{coalesce(outputs('GetFormSubmissionExpand')?['body/msdynmkt_createdentity/_msdynmkt_targetcontact_value'],outputs('CreateContact')?['body/contactid'])}
Description: outputs('FormSubmissionJSON')?['Comments']
Update the ‘Linked Record’ to redirect to the Case
Another ‘Upsert’ on the form submission linked record. Now we are going to link it to the Case, so when the ‘Linked Record’ is selected, the redirect will automatically open the Case. Yay!
Dataverse: Upsert a row - x
Table name: Created linked entity
Row ID: coalesce(outputs('GetFormSubmissionExpand')?['body/_msdynmkt_createdentity_value'],outputs('UpsertLinkedRecordContact')?['body/msdynmkt_createdentitylinkid'],guid())
Name: outputs('CreateCase')?['body/_customerid_value@OData.Community.Display.V1.FormattedValue'] outputs('CreateCase')?['body/casetypecode@OData.Community.Display.V1.FormattedValue']
Target entity: incident
Target entity Id: outputs('CreateCase')?['body/incidentid']
Does a Lead need to be created?
If the Enquiry Type selected was ‘Getting a quote’ (1) or ‘Our products and services’ (2) or ‘Something else’ (0), and also there is no matched lead already attached, then a lead needs to be created.
Control: Condition - Lead
outputs('ContactUsEnquiryTypeResponse')
is less than or equal to
2
AND
outputs('GetFormSubmissionExpand')?['body/msdynmkt_createdentity/_msdynmkt_targetlead_value']
is equal to
null
Create a Lead using Form Submission Data
If the enquiry type aligns, we need to use the submitted form data to create a new Lead. Make sure you link it to the Source Form and Parent Contact, also define any ownership and additional defaults you might need for Lead creation.
Dataverse: Add a new row - CreateLead
Table name: Leads
First Name: outputs('FormSubmissionJSON')?['First Name']
Last Name: outputs('FormSubmissionJSON')?['Last Name']
Email: outputs('FormSubmissionJSON')?['Email']
Mobile Phone: outputs('FormSubmissionJSON')?['Mobile Phone']
Topic: outputs('GetFormSubmissionExpand')?['body/msdynmkt_marketingformid/msdynmkt_name']
Company Name: outputs('FormSubmissionJSON')?['Company Name']
Enquiry Type: outputs('ContactUsEnquiryTypeResponse')
Description: outputs('FormSubmissionJSON')?['Comments']
Parent contact for lead: if(equals(outputs('GetFormSubmissionExpand')?['body/msdynmkt_createdentity/_msdynmkt_targetcontact_value'],null),null,concat('contacts/',outputs('GetFormSubmissionExpand')?['body/msdynmkt_createdentity/_msdynmkt_targetcontact_value']))
Source form: msdynmkt_marketingforms/@{outputs('GetFormSubmissionExpand')?['body/msdynmkt_marketingformid/msdynmkt_marketingformid']}
Update the ‘Linked Record’ with the new Lead
‘Upsert’ the form submission linked record to redirect to the Lead, and also attribute the associate Contact if found.
Dataverse: Upsert a row - UpsertLinkedRecordLead
Table name: Created linked entity
Row ID: coalesce(outputs('GetFormSubmissionExpand')?['body/_msdynmkt_createdentity_value'], guid())
Name: outputs('CreateLead')?['body/fullname']
Target entity: lead
Target entity Id: outputs('CreateLead')?['body/leadid']
Contact record: if(equals(outputs('GetFormSubmissionExpand')?['body/msdynmkt_createdentity/_msdynmkt_targetcontact_value'],null),null,concat('contacts/',outputs('GetFormSubmissionExpand')?['body/msdynmkt_createdentity/_msdynmkt_targetcontact_value']))
Lead record: leads/@{outputs('CreateLead')?['body/leadid']}
Update the form submission ‘Linked Record’
This links everything back together, so that when you open the form submission, you can select the ‘Linked Record’ and get redirected to the correct Lead or Case that was generated of the back of this submission.
Dataverse: Update a row - UpdateFormSubmission
Table name: Form Submissions
Row ID: triggerBody()['text']
Linked Record: msdynmkt_createdentitylinks/@{coalesce(outputs('UpsertLinkedRecordLead')?['body/msdynmkt_createdentitylinkid'],outputs('UpsertLinkedRecordCase')?['body/msdynmkt_createdentitylinkid'],outputs('GetFormSubmissionExpand')?['body/msdynmkt_createdentity/msdynmkt_createdentitylinkid'])}
Respond to the parent flow
Tell the parent flow you are finished.
PowerApps: Respond to a PowerApp or flow
No inputs
Back to the Parent Flow
Call the child flow when case or lead creation is required
Jump back to your main/parent flow which is triggered by the form submission, in the condition ‘Create Lead or Case’ in the Yes branch, call the child flow you just created.
Give it a try
That’s it, you should be able to submit the marketing form and automatically create the correct corresponding Case or Lead from a single form, and the ‘Linked Record’ points to the correct result too. What a beauty!