Trigger Journey In Marketing Cloud from Sales Cloud ON Record Update
Tags: salesforce, marketingcloud, journey, apex
Published: 2021-08-07 07:08:04

**Scenario**: we have to send email from Marketing Cloud to the contact of an opportunity whenever opportunity records update to some specific field values like its type or stage.

## Setup
You should have connected salesforce CRM with marketing cloud by using [marketing cloud connector](https://trailhead.salesforce.com/en/content/learn/modules/marketing-cloud-connect).

# Process !
We will create a trigger in sales cloud so whenever opportunity update our trigger will run and class our trigger handeler class in which we have write code to hit marketing cloud api to trigger event in marketing cloud.
[Download Postman Collection](https://github.com/shivamkapasia0/blogs/blob/main/Event-Interaction%20SC-MC.postman_collection.json)

### In Marketing Cloud

 - [Create a Marketing CLoud App](https://developer.salesforce.com/docs/atlas.en-us.noversion.mc-app-development.meta/mc-app-development/create-a-mc-app.htm) for Client Secret, Client Id, Client Secret, Auth URL.
 - Go to journey builder and select **[Api Event](https://developer.salesforce.com/docs/atlas.en-us.noversion.mc-apis.meta/mc-apis/how-to-fire-an-event.htm)** as a starting source and configure it by choosing any Data Extension which will be used to store information which we will sent through api from sales cloud and we can use this information to send email in journey builder.
 - You can add as fields as per your choice but for this case we only need email as a primary key and ContactKey for contact Id, By using ContactKey we can query data from AmpScript like below which will be used in our email template:
 
```
This Code will be used in our email template that will be sent by journey to contact's email
%%[       
/* ContactKey will be Contact Id from Sales Cloud */
SET @ContactId= AttributeValue("ContactKey") 
IF Not Empty(@ContactId) THEN
/* Querying Contact Object by using Id as a filter */
SET @subscriber = RetrieveSalesforceObjects("Contact", "Phone, LastName, Email", "Id", "=", @ContactId )
      SET @subscriberPhone = Field( Row(@subscriber, 1), "Phone")
      SET @subscriberEmail = Field( Row(@subscriber, 1), "Email")
      SET @subscriberLastName = Field( Row(@subscriber, 1), "LastName")
ENDIF
]%%
// Displaying attributes in HTML.
<b>Last Name :</b> %%=v(@subscriberLastName)==%%
<b>Email :</b> %%=v(@subscriberEmail)==%%
```
### In Sales Cloud
 - write trigger on any object we are using opportunity in this case so we will be using trigger on opportunity object.
```
trigger OpportunityTrigger on opportunity(after insert, after update) {
    Set<ID> contactIdSet = new Set<ID>();
    for(opportunity oppObj: Trigger.New){
        if(oppObj.stagename  == 'Closed Won' && String.isNotEmpty(oppObj.contactId)){
            contactIdSet.add(oppObj.contactId);
        }
    }
   // we will send email to multiple contacts that's why sending multiple contacts id's
    if(contactIdSet.size() > 0){ 
        MarketingCloudApiHandelerClass.TriggerEventFunction(contactIdSet);
    }
}
```
- First we need access token to trigger the event in marketing cloud for this you need client id, secret id, account id and auth url which you can get from your package in marketing cloud, you can first try with postman
**Here is code snippet in cURL for Access Token:**
```
curl --location --request POST 'your_auth_URL/v2/token' \

--header 'Content-Type: application/json' \

--data-raw '{

"grant_type": "client_credentials",

"client_id": "your_client_id",

"client_secret": "your_client_secret",

"account_id": "your_account_id"

}'
```
**Apex Code Snippet:**
```
public class MarketingCloudApiHandelerClass {
    
    @Future(callout=true)
    public static void TriggerEventFunction(Set<ID> contactIdSet){
        String clientId = 'your_client_id';
        String clientSecret = 'your_client_secret';
        String accountID = 'your_client_id';
        String eventKey = 'your_API_event_key';
        String jsonBody = GetAccessTokenJsonBody(clientId, clientSecret, accountID).getAsString(); 
        String authURL = 'your_auth_URL';
        String accessToken;
        Http h = new Http();
        HttpRequest req = new HttpRequest();
        req.setEndpoint(authURL);
        req.setHeader('Content-Type', 'application/json');
        req.setMethod('POST');
        req.setBody(jsonBody);
        
        HttpResponse res = h.send(req);
        String responseBody = res.getBody();
        Map<String, Object> result = (Map<String, Object>)JSON.deserializeUntyped(responseBody);
        
        if(res.getStatusCode() == 200){
            accessToken = 'Bearer '+result.get('access_token').toString();
            }
       }
       
  public static JSONGenerator GetAccessTokenJsonBody(String clientID, String clientSecret, String accountID){
    JSONGenerator gen = JSON.createGenerator(true);
    gen.writeStartObject();
    gen.writeStringField('grant_type', 'client_credentials');
    gen.writeStringField('client_id', clientID);
    gen.writeStringField('client_secret', clientSecret);
    gen.writeStringField('account_id', accountID);
    gen.writeEndObject();
    return gen;
}
```
**For Event Interaction/Trigger**
**cURL Code Snippet:**
**Note:**
*ConatctKey will be contact Id and Email Address will be contact's email on which you will be sending email thorugh journey, journey will used this email as reciepnts email and contact id as primary key and we will be using this to query salesforce records thorugh ampScript.*
```
curl --location --request POST 'your_rest_url_from_package/interaction/v1/events' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer access_token_here' \
--data-raw '{
    "ContactKey" : "0031700001YUeUZBB1",
    "EventDefinitionKey" : "your_APIEvent_Key,
    "Data": {
        "ContactKey" : "0031700001YUeUZBB1",
        "Email Address":"kapasiashivam007@gmail.com"
    }
}'
```
**Apex Code Snippet:**
```
 String EventJsonBody = GetEventInteractionJSONBody(conObj.Id, conObj.Email, eventKey).getAsString();  
                Http eventHttp = new Http();
                HttpRequest eventReq = new HttpRequest();
                eventReq.setEndpoint(baseEventURL);
                eventReq.setHeader('Content-Type', 'application/json');
                eventReq.setHeader('Authorization', accessToken);
                eventReq.setMethod('POST');
                eventReq.setBody(EventJsonBody);
                
                HttpResponse eventRes = eventHttp.send(eventReq);
                String EventResponseBody = eventRes.getBody();
                Map<String, Object> EventResponseResult = (Map<String, Object>)JSON.deserializeUntyped(EventResponseBody);
                if(eventRes.getStatusCode() == 201){
                    system.debug('EventResponseBody::' + EventResponseBody);
                }

public static JSONGenerator GetEventInteractionJSONBody(String contactKey, String email, String eventKey){
    JSONGenerator gen = JSON.createGenerator(true);
    gen.writeStartObject();
    gen.writeStringField('ContactKey', contactKey);
    gen.writeStringField('EventDefinitionKey', eventKey);
    gen.writeFieldName('Data');
    gen.writeStartObject();
    gen.writeStringField('ContactKey', contactKey);
    gen.writeStringField('Email Address', email);
    gen.writeEndObject();
    gen.writeEndObject();
    return gen;
}  
```
**I hope you get some idea about how can you triggered ApiEvent in a Journey thorugh Salesforce CRM**