Zay Aung

Dynamics 365, Power Platform, and everything in between

Tag: Contact Point Consent

  • Migrate Contacts and Contact Point Consents (CPC) into Customer Insights – Real-time Journey

    Migrate Contacts and Contact Point Consents (CPC) into Customer Insights – Real-time Journey

    In this post, I’ll walk you through how to migrate Contacts together with Contact Point Consents (CPC) from an external source into Customer Insights – Journeys (CI-J).

    1. Requirements Covered in This Post
    2. Create Custom Raw Contact Table
    3. Create Power Automate Flow to Process Raw Contact from the External Source
      1. When a row is added – Raw Contact
      2. List rows – Contact Filter by Email
      3. Condition – Email Match Found
      4. List rows – Contact Point Consent
      5. Select – CPC
      6. Filter – Commercial Consent Status
      7. Condition – Commercial Consent Status Return Result
      8. Filter – Monthly Newsletter Consent Status
      9. Condition – Monthly Newsletter
      10. Delete a row – Raw Contact
    4. Testing the solution
    5. Considerations
    6. Summary

    If you ever come across a requirement to migrate or upgrade from a previous marketing system – and need to carry over existing consent records – you’ll need to plan how to migrate both Contacts and their related CPCs effectively into CI-J.

    If you’re only importing CPCs separately (i.e., Contacts have already been migrated to Dataverse), then you can use the out-of-the-box (OOTB) functionality, which is well documented in this post by Megan V. Walker: How To Import Contact Point Consent Records. In that case, feel free to skip this blog entirely.

    Requirements Covered in This Post

    In this post, we’ll focus on the following use case:

    • Both Contacts and CPCs are imported together using an Excel file.
    • Contacts are upserted – if a Contact doesn’t exist, it’s created; if it does, it’s updated.
    • CPCs are created or updated alongside the Contact.

    Notes:

    1. We’ll use email as the unique identifier for Contacts (a common practice).
    2. CPCs will include:
      • Purpose = Commercial
      • Topic = Newsletter
    3. The solution will only focus on Email channel.

    Below is the conceptual diagram of how to achieve the requirements.

    Fig: Solution Conceptual Diagram

    Create Custom Raw Contact Table

    We start by creating a custom table called Raw Contact, with the following columns:

    NameData TypeValuesNotes
    First NameSingle line of textN.A
    Last NameSingle line of textN.A
    Commercial Consent StatusChoiceNot Set
    Opted In
    Opted Out
    You can use OOTB Choice – Consent Value
    Monthly Newsletter Consent StatusChoiceNot Set
    Opted In
    Opted Out
    You can use OOTB Choice – Consent Value
    Raw Contact Form
    Fig: Raw Contact Form

    Create Power Automate Flow to Process Raw Contact from the External Source

    To process the data, we’ll use Power Automate to:

    • Upsert Contacts
    • Create/update related CPCs
    • Remove the processed Raw Contact record

    Below is the overview of the Flow.

    Fig: Raw Contact – Add Contact and Contact Point Consent PA

    When a row is added – Raw Contact

    First, the Flow will be triggered when the Raw Contact record is added (e.g., from Excel import).

    Fig: When a row is added – Raw Contact

    List rows – Contact Filter by Email

    Next, we will include List rows to filter Contact by Email. As you can see from the screen, I’ve included Sort By = modifiedon desc and Row count = 1. That means for some reason, if there’re multiple Contacts with the same email, we’ll only update the latest Contact.

    Fig: List rows – Contact Filter by Email

    Condition – Email Match Found

    These actions are pretty straight forward. As mentioned in the above, this will upsert the Contact.

    Fig: Condition – Email Match Found
    Fig: Email Match Found – Condition expression

    This action will list CPC rows with Contact’s email to check if CPC record already exists.

    Fig: List rows – Contact Point Consent

    Select – CPC

    This action will transform the shape of objects in an array so that I can reuse it easily to further filtering. One thing to call out here is that for _msdynmkt_topicid_value column, I’ve used the below expression to replace with null for the general Commercial Purpose without associating with Topic.

    if(equals(contains(string(item()),'_msdynmkt_topicid_value'),true),item()?['_msdynmkt_topicid_value'],null)
    Fig: Select – CPC

    This action will filter the particular CPC record where:

    • Contact point value = [Contact’s Email] and
    • Purpose = Commercial and
    • Topic = null (the null value is assigned in the above step) and
    • Channel = Email

    Below is the expression I’ve used to filter the above conditions to check if the CPC record already exists.

    and(equals(item()?['msdynmkt_contactpointvalue'],triggerOutputs()?['body/bs_email']),equals(item()?['_msdynmkt_purposeid_value'],'[Replace with Commercial Purpose GUID]',equals(item()?['_msdynmkt_topicid_value'],null),equals(item()?['msdynmkt_contactpointtype'],534120000))
    Fig: Filter – Commercial Consent Status
    Fig: Example result of “Filter – Commercial Consent Status”

    Based on the result from the above filter – Commercial Conset Status – we will then upsert CPC record for Commercial Purpose that is not associated with any Topic.

    Fig: Condition – Commercial Consent Status Return Result
    Fig: Commercial Consent Status – Condition expression

    While “Update a row” and “Add a new row” actions are pretty straight forward, a few things to call out.

    • On “Update a row – CPC – Commercial Consent Status” action, below is the expression to get Row ID of the particular CPC record.
    first(body('Filter_-_Commercial_Consent_Status'))?['msdynmkt_contactpointconsent4id'] 
    Fig: Update a row – CPC – Commercial Consent Status action
    • On “Add a new row – CPC – Commercial Consent Status” action, make sure to follow the correct format to update Commercial Purpose lookup, and replace with Commercial Purpose GUID.
    Fig: Add a new row – CPC – Commercial Consent Status action

    Similar to the above filter action, this action will filter particular CPC record where:

    • Channel = Email and
    • Purpose = Commercial and
    • Topic = Monthly Newsletter and
    • Contact point value = [Contact’s Email]
    Fig: Filter – Monthly Newsletter Consent Status
    Fig: Example result of “Filter – Monthly Newsletter Consent Status”

    Condition – Monthly Newsletter

    Based on the result from the above filter – Monthly Newsletter Consent Status – we will then upsert CPC record for Monthly Newsletter Topic.

    Note: As mentioned in Condition – Commercial Consent Status Return Result, follow the same to get Row ID in “Update a row”, and follow the correct format to populate Commercial Purpose lookup.

    Fig: Monthly Newsletter – Condition expression

    Delete a row – Raw Contact

    Once upsert Contact and CPC record, the final action is to delete Raw Contact record that you’ve imported to Raw Contact table. This will enable business users to check easily if processing of Raw Contacts complete.

    After that, validate the Flow make sure if there’s no error, and once done, Publish it.

    Testing the solution

    Once published, import the data to Raw Contact using Excel data template. The Flow will be triggered and process Raw Contact record. If the Flow is run successfully, it will upsert Contact and associated CPC.

    Fig: Raw Contact Excel data template
    Fig: Contact form
    Fig: Contact Point Consent

    Considerations

    There are a few practical considerations to be aware of:

    • OOTB Data Import Limits: The amount of record you can upload to Dataverse using OOTB Data Import functionality is limited.
    • Power Platform Request Limits: The number of request Power Platform can handle within 24 hours also has limit – the limit varies based on which plan you’re on.

    Summary

    In this blog post, we’ve:

    • Created a custom Raw Contact table
    • Built a Flow to process and upsert Contacts and CPCs
    • Validated the results through testing
    • Shared considerations for volume and scalability

    Let me know if you’ve implemented something similar, or if you face any issues during your migration journey!