2

ObJective: I am attempting to create a new prospect in Pardot when a lead that had no email gets updated with an email (Pardot will sync accounts but until the lead email exist there is no prospect to sync, hence this trigger)

Problem: Using the afterUpdate trigger context I was able to verify the email status to make this call only when expected, but the problem is making the dynamically generated email "execute." So my Pardot class method creates the URL like so:

String add_prospect = 'https://pi.pardot.com/prospect/sync/email/'+l.Email+'?lead_id='+l.Id+'&sessionid='+UserInfo.getSessionId()+'&serverurl='+l.Partner_Server_URL__c;

Then I send the URL to the sendHttpRequest() method and from what I can see the developer console shows success but my Pardot account does not show the new account. In addition when I take the generated URL from the developer console and paste into address bar and run it I get directed to Pardot where the prospect is successfully created.

Here is the Developer Console response:

13:02:58:065 CALLOUT_REQUEST [38]|System.HttpRequest[Endpoint=https://pi.pardot.com/prospect/sync/email/newprospect@email.com?lead_id={my_lead_id}&sessionid={my_sessionid}&serverurl=https://cs10.salesforce.com/services/Soap/u/9.0/{org_id}, Method=POST]
13:03:00:421 CALLOUT_RESPONSE [38]|System.HttpResponse[Status=OK, StatusCode=200]

And here is the method in question:

@future (callout=true) // future method needed to run callouts from Triggers

static void sendHttpRequest(String url){
    /* Instantiate a new http object */
    Http h = new Http();

    /* Instantiate a new HTTP request, specify the method (GET) as well as the endpoint */
    HttpRequest req = new HttpRequest();
    req.setEndpoint(url);
    req.setMethod('POST'); //I tried GET as well
    req.setTimeout(60000);

    // Send the request, and return a response
    HttpResponse res = h.send(req);
}

This is my first trigger/class so apologies if I'm missing something obvious but hoping if that's the case that the SF community can help me out. If there is a details I left out that you need let me know in comments and I'll get that added

References: http://www.pardot.com/faqs/salesforce/setting-up-salesforce-com-person-accounts-for-pardot-syncing/#Send_to_Pardot_button

  • 2
    You should System.debug(res.getBody()); or otherwise check what body comes back. If there is a problem with the session ID you are passing, a HTML login page is likely to be returned with a status of 200 and because the request is unauthenticated no change will be made. – Keith C Oct 3 '14 at 21:56
  • Did that and got this response: 17:17:02:137 USER_DEBUG [39]|DEBUG|<!doctype html> – Xtremefaith Oct 4 '14 at 0:18
  • I changed method to GET again and now getBody() comes back with html for what appears is the Pardot login screen as you predicted. So what do you suggest I do about this? – Xtremefaith Oct 6 '14 at 18:39
  • If there is any sort of log at the Pardot side it would be worth a look to see if anything useful is said there. I saw this scary post a while ago Different Session Ids in Different contexts; if you can it might be worth trying any other session ID you can get your hands on. Apart from Googling, otherwise you might post here again with the extra information... – Keith C Oct 6 '14 at 19:09
0

You have to pass the sessionId from the place you are making the call. So, here it should be from the trigger as follows,

trigger AllLeadTrigger on Lead(after insert){

       Lead l = Trigger.new[0];//Passing the single record

       ClassName.sendHttpRequest(l.id,UserInfo.getSessionId());

}

And the Future method code like,

@future (callout=true) // future method needed to run callouts from Triggers

static void sendHttpRequest(Id leadID, String userSessionId){

    Lead leadRec = [select id,Email,Partner_Server_URL__c from Lead where Id =: leadID];

    String url = 'https://pi.pardot.com/prospect/sync/email/'+ leadRec.Email+'?lead_id='+ leadRec.Id+'&sessionid='+userSessionId+'&serverurl='+leadRec.Partner_Server_URL__c;

    Http h = new Http();

    /* Instantiate a new HTTP request, specify the method (GET) as well as the endpoint */
    HttpRequest req = new HttpRequest();
    req.setEndpoint(url);
    req.setMethod('POST'); //I tried GET as well
    req.setTimeout(60000);

    // Send the request, and return a response
    HttpResponse res = h.send(req);
}

Hope this solves your issue.

  • As @Keith C commented, my http request was working but I was running into a login page therefore my request wasn't being run through Pardot, so I've since had to use the API. I'm working on this solution right now and will post an answer as soon as I have it complete. Thanks for you input though, really appreciate it – Xtremefaith Oct 10 '14 at 19:20
1

The problem was simply that when the call was made I did not have access, using the Pardot API I realized to make an API call I will need to first get an API key (by sending email, password, and user_key), then every API call will require the api_key and the user_key along with any parameters need for the request you're making.

In short here is the code from my approach.

In my Pardot.cls (which is used by my trigger and trigger handler class) I have methods like createProspectsByLead() which fires APIRequest() that first gets the API Key, and then uses that key and the user_key to make another HttpRequest.

The full code implementation can be found here

All API Request use this method

@future (callout=true)
private static void APIRequest(String url, String body){
    HttpResponse response = httpCallout( url, 'user_key='+getConnectorUserKey()+'&api_key='+getAPIKey()+'&'+ body );
}

Get API Key

public static String getAPIKey(){
    HttpResponse response = httpCallout(
        'https://pi.pardot.com/api/login/version/3?', //URL
        'email='+getConnectorEmail()+'&password='+getConnectorPassword()+'&user_key='+ getConnectorUserKey() //Body
    );

    /* Parse API Response */
    Dom.Document doc = new Dom.Document();
    doc.load(response.getBody());
    Dom.XMLNode root = doc.getRootElement();
    if(root.getName()=='rsp') {
        for(Dom.XMLNode node1: root.getChildElements()) {
            if(node1.getName()=='err') {
                String err = root.getChildElement('err', null).getText();
                String code = root.getChildElement('err', null).getAttribute('code', null);
                System.debug('::API REQUEST ERROR:: '+code+' - '+err);
                return err;
            }
            if(node1.getName()=='api_key') {
                /* Store API in variable */
                // TODO: Store API for 1 hour in Global__c
                String api_key = root.getChildElement('api_key', null).getText();
                return api_key;
            }
        }
    }

    /* This should never happen */
    return '';
}

Each callout uses the httpCallout method

public static HttpResponse httpCallout(String url, String body){
    HttpRequest     request     = new HttpRequest();
    HttpResponse    response    = new HttpResponse();
    Http            http        = new Http();

    request.setEndPoint(url);
    request.setBody(body);
    request.setMethod('POST');

    /* Try to send the request */
    try {
        response = http.send(request);
        System.debug('::RESPONSE::'+response.getBody());
        return response;
    } catch(System.CalloutException e) {
        System.debug('ERROR: '+ e);
        return null;
    }
}

Be sure to see my github repo of this complete implementation and even contribute to it as a community resource.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.