Integrating Salesforce with TUNE
As a TUNE customer, you may need to integrate your tracking flow with your other SaaS vendors. This document describes a simple use case for integrating a TUNE Postback Tracking flow in Salesforce using Apex.
You will need to be familiar with the Apex development process for writing, testing, and deploying your code to your Salesforce instance: Salesforce Developers
Example
Consider the following scenario: As a partner marketing manager using Salesforce, I want to record a conversion on a new Salesforce Lead. As the Lead becomes an Opportunity, I want to record an additional conversion when the Opportunity closes.
To achieve this, we have set up an offer in TUNE called "My Campaign" with goals enabled. We will use the Default Goal to track new leads with the tracking protocol of Server Postback with Transaction ID. The offer also has a goal that we will use in the event that a contract is signed, called "Contract Signed", and its tracking protocol is also Server Postback with Transaction ID.
For our example, we use a Marketo form to capture the Transaction ID in a form field when the user lands on the page. When the form is submitted, it creates the new Lead in Salesforce and stores the Transaction ID in the Lead field so that we can post back with it when the contract is signed. Meanwhile, we'll send a conversion postback for the form submission as a new Lead:
<script>
MyMarketoForm.whenReady(function(form) {
var url = new URL(window.location.href);
var transaction_id = url.searchParams.get("transaction_id");
form.onSuccess(function() {
$.ajax({
type: "GET",
url: "https://mytrackingdomain.go2cloud.org/aff_lsr",
data: {
offer_id: 1,
transaction_id: transaction_id
},
async: false,
success: function(response) {
console.log(response);
}
})
})
}
})
</script>
We then use an Apex Trigger to convert to an Opportunity:
/*
* LeadConversionTrigger is a trigger attached to Lead objects
* This trigger fires on the `after insert` event
*/
trigger LeadConversionTrigger on Lead (after insert) {
try {
LeadStatus convertStatus = [SELECT Id, MasterLabel FROM LeadStatus WHERE IsConverted=true LIMIT 1];
Id campaignId = [SELECT Id FROM Campaign WHERE Name = 'My Campaign'].Id;
Id ownerId = [SELECT Id FROM User WHERE Email = 'partnermanager@tune.com'].Id;
for (Lead lead: Trigger.new) {
Database.LeadConvert lc = new Database.LeadConvert();
lc.setLeadId(lead.id);
lc.setConvertedStatus(convertStatus.MasterLabel);
lc.setOwnerId(ownerId);
lc.setOpportunityName('Opportunity - ' + lead.FirstName + ' ' + lead.LastName + ' (' + lead.Email +')');
Database.LeadConvertResult lcr = Database.convertLead(lc);
System.assert(lcr.isSuccess());
}
} catch (Exception e) {
// Log exception
System.debug(e.getTypeName() + ': ' + e.getMessage() + ' - Line ' + e.getLineNumber());
}
}
Let’s create a MyCampaignPostback class that will send a Postback for a goal of your My Campaign offer when the Opportunity is closed. For this offer, we’ll use the transaction_id parameter so we can attribute correctly, and we also want to use the amount parameter, where we’ll pass the contract value associated with the Opportunity.
We’ll use Apex Http Classes to send the Postback:
/*
* MyCampaignPostback sends a Postback for the My Campaign offer (offer id = 1)
* transaction_id: the ID stored when the user landed on the page which we use to attribute the conversion to the click
* amount: the dollar value of the sale
*/
public class MyCampaignPostback {
@future(callout=true)
public static void send(Decimal transactionId, Decimal amount) {
Http http = new Http();
HttpRequest request = new HttpRequest();
// the goal conversion URL with the relevant parameters
request.setEndpoint('http://mytrackingdomain.go2cloud.org/aff_goal?a=lsr&goal_name=contract-signed&offer_id=1&transaction_id=' + transactionId + '&amount=' + amount);
request.setMethod('GET');
HttpResponse response = http.send(request);
// log response
System.debug(response.getBody());
}
}
Now, let’s use an Apex trigger that will invoke the send method of the MyCampaignPostback class when the Opportunity closes:
/*
* This trigger will fire on `after update` events for Opportunities
*/
trigger MyCampaignPostbackTrigger on Opportunity (after update) {
for(Opportunity opp: Trigger.new){
// MyCampaignPostback.send needs the affiliate id and contract value from the Opportunity
MyCampaignPostback.send(opp.Transaction_Id__c, opp.Total_Contract_Value__c);
}
}