1

There are several focused questions on this topic but after trying them all I felt the need to seek out help. I am using Sendgrid, their webhook sends a json response and for some reason I have been unable to figure out how to integrate with our CRM.

Update: 12/3/2015 @ 1:01pm - I got some code to work (probably not the most efficient but it works) see below.

Example JSON from Sendgrid being sent:

    [
  {
    "sg_message_id":"sendgrid_internal_message_id",
    "email": "john.doe@sendgrid.com",
    "timestamp": 1337197600,
    "smtp-id": "<4FB4041F.6080505@sendgrid.com>",
    "event": "spamreport"
  },
  {
    "sg_message_id":"sendgrid_internal_message_id",
    "email": "john.doe@sendgrid.com",
    "timestamp": 1337966815,
    "category": "newuser",
    "event": "bounce",
    "url": "https://sendgrid.com"
  },
  {
    "sg_message_id":"sendgrid_internal_message_id",
    "email": "john.doe@sendgrid.com",
    "timestamp": 1337969592,
    "smtp-id": "<20120525181309.C1A9B40405B3@Example-Mac.local>",
    "event": "unsubscribe",
    "asm_group_id": 42
  }
]

The issue I am running into is that each array in the JSON pertains to a particular event. For example "Spam", or "Bounced" or "Unsubscribe". I've set it up so that only those three events are sent. However there is a possibility that someone will bounce first, then get it, then hit spam, then hit unsubscribe.

The simplest solution for this (disregarding a heirarchy system) is to have each of these events pass along to a specific field in our CRM. For example if the event = spam, then it would fill $spam with "spam". However if it is not present it should do nothing.

One last note, I have to pass a header across so that Sendgrid will stop spamming the script. Also I am not a coder, or programmer, I have just picked up a few things over the last few months.

My Script that Isn't Working:

        <?php

    $data = file_get_contents("php://input");
    $events = json_decode($data, true);

    require_once('Infusionsoft/infusionsoft.php');
    $contact = new Infusionsoft_Contact();

    $custom = array(
    '_SGBounce',
    '_SGSpam',
    '_SGUnsub'
    );
    $contact->addCustomFields($custom);

if (is_array($events) || $events instanceof Traversable) {    
foreach ($events as $event) {
        $email = $event['email'];
        if($event['event'] === 'bounce') {
            $bounce = 'bounce';
        } elseif ($event['event'] === 'spamreport') {
            $spam = 'spam';
        } elseif ($event['event'] === 'unsubscribe') {
            $unsub = 'unsubscribe';
        } else {
            die echo header("HTTP/1.1 200 OK");
    }
        process_event($event);
    }}
    if (empty($email)) {
        die echo header("HTTP/1.1 200 OK");
    } else {
        $contact->Email = $email;
        $contact->_SGBounce = $bounce;
        $contact->_SGSpam = $spam;
        $contact->_SGUnsub = $unsub;
        $contact->save();
    }

    header("HTTP/1.1 200 OK");
    ?>

I also have a script I am using that writes to a file, just to test and see if I can get the correct events to write. However I have been unsuccessful to get it to iterate past the first array. I've tried nesting the foreach() in another foreach() with a key => value solution posted in another answer here. However that was also a dead end.

Any tips, help, and guidance... would be greatly appreciated.

Update: Working Code Below (in case this helps someone)

<?php

$data = file_get_contents("php://input");
$events = json_decode($data, true);

require_once('Infusionsoft/infusionsoft.php');
$contact = new Infusionsoft_Contact();

$custom = array(
'_SendGrid',
);
$contact->addCustomFields($custom);

$emails = array();
$em = '';

if (is_array($events) || $events instanceof Traversable) {
    foreach ($events as $event) {
    $email = $event['email'];
    $em = $email;
    if($event['event'] === 'unsubscribe') {
        $event = 'unsubscribe';
        $unsubscribe = 'unsubscribe';
    } elseif($event['event'] === 'spamreport') {
        $event = 'spam';
        $spam = 'spam';
    } elseif($event['event'] === 'bounce') {
        $event = 'bounce';
        $bounce = 'bounce';
    } else {
        continue;
    }
    $default = array(
        'bounce' => false,
        'spam' => false,
        'unsubscribe' => false
    );
    if(!is_null($event)) {
        if(array_key_exists($email, $emails)) {
            $entry = $emails[$email];
        } else {
            $entry = $default;
        }

        switch($event) {
            case "bounce":
                $entry['bounce'] = true;
                break;
            case "spam":
                $entry['spam'] = true;
                break;
            case "unsubscribe":
                $entry['unsubscribe'] = true;
                break;
        }
    }
}}
if($unsubscribe === 'unsubscribe'){
    $param = 'unsubscribe';
} elseif($spam === 'spam'){
    $param = 'spam';
} elseif($bounce === 'bounce'){
    $param = 'bounce';
} else {
    echo header("HTTP/1.1 200 OK");
}

$contact->Email = $em;
$contact->_SendGrid = $param;
$contact->save();

header("HTTP/1.1 200 OK");
?>
Kevin
  • 13
  • 3
  • you're setting vars in a loop, and then using the vars later on. that means you'll only ever get the data from the LAST $event that was processed stored in $contact... – Marc B Dec 03 '15 at 17:26
  • Ahh makes sense. Since the size of the JSON string (ie: # of arrays) is dynamic and I may not know how many arrays or values will exist, do I have to add each value to an array to keep the first, second, and so on events to make sure they are stored? Thank you by the way for the fast response. – Kevin Dec 03 '15 at 17:30
  • pretty much. if sendgrid provides a unique id for each of these events, you could use that as the key, e.g. `$contact[$uniquekey]->email = $email`, and do that inside the foreach loop. – Marc B Dec 03 '15 at 17:31
  • The example of the JSON they send is above, however it didn't look like there was a unique key above each array or assigned to the whole string. I'm not sure if it's useful but I do see that the timestamp is unique for each JSON array. – Kevin Dec 03 '15 at 17:33
  • see they have a place for the id within each array. The email is not nested (multidimensionally) below that id... for example using `$event['sg_message_id']['email'] = $email` doesn't work for me. Neither does `foreach ($events as $events['timestamp'] => $event) { $event['email'] = $email;` – Kevin Dec 03 '15 at 17:43
  • You should be using if, ifelse, ifelse, else.... – VIDesignz Dec 03 '15 at 17:55
  • Updated the if, elseif, elseif, and else thanks to VIDesignz. Also wanted to add response to drew010; my json decode is set to true, which is why I was using the [ ' item '] format. – Kevin Dec 03 '15 at 18:07

1 Answers1

0

What you could do, is process it like this;

$emails = array();

foreach ($events as $event) {
    $email = $event['email'];
    if($event['event'] === 'bounce') {
        $event = 'bounce';
    } elseif ($event['event'] === 'spamreport') {
        $event = 'spam';
    } elseif ($event['event'] === 'unsubscribe') {
        $event = 'unsubscribe';
    } else {
        continue;
    }
    // Set defaults
    $default = array(
        'bounce' => false,
        'spam' => false,
        'unsubscribe' => false
    );
    if(!is_null($event)) {
        if(array_key_exists($email, $emails)) {
            $entry = $emails[$email];
        } else {
            $entry = $default;
        }

        switch($event) {
            case "bounce":
                $entry['bounce'] = true;
                break;
            case "spam":
                $entry['spam'] = true;
                break;
            case "unsubscribe":
                $entry['unsubscribe'] = true;
                break;
        }
    }
}

Then you'd end up with a list of emails that are their own array with boolean values for keys bounce, spam and unsubscribe. You could do a loop over that array to save the data.

Ieuan
  • 1,140
  • 1
  • 12
  • 27
  • Leuan thank you for the response! I added your snippet and tried testing it. Please forgive my lack of code knowledge here, but I would have the emails in an array inside `$emails` correct? What about the events? Is it `$event`? If I did `var_dump($emails)` or `var_dump($event)` I would have the values? I need to pass the email and the value to my CRM, and from what I can tell the SendGrid webhook has only 1 associated email with each response, so maybe an array of emails isn't needed? Thanks for feedback – Kevin Dec 03 '15 at 18:45
  • Got some code to work, updated the original. Thank you for the suggestion leuan. – Kevin Dec 03 '15 at 21:27