"ActivityRecord", "ActivityTypeFilter" => "ActivityTypeFilter", "Attribute" => "Attribute", "AuthenticationHeaderInfo" => "AuthenticationHeaderInfo", "CampaignRecord" => "CampaignRecord", "LeadActivityList" => "LeadActivityList", "LeadChangeRecord" => "LeadChangeRecord", "LeadKey" => "LeadKey", "LeadRecord" => "LeadRecord", "LeadStatus" => "LeadStatus", "ListKey" => "ListKey", "ResultGetCampaignsForSource" => "ResultGetCampaignsForSource", "ResultGetLead" => "ResultGetLead", "ResultGetLeadChanges" => "ResultGetLeadChanges", "ResultGetMultipleLeads" => "ResultGetMultipleLeads", "ResultListOperation" => "ResultListOperation", "ResultRequestCampaign" => "ResultRequestCampaign", "ResultSyncLead" => "ResultSyncLead", "ResultSyncMultipleLeads" => "ResultSyncMultipleLeads", "StreamPosition" => "StreamPosition", "SyncStatus" => "SyncStatus", "VersionedItem" => "VersionedItem", "ArrayOfActivityRecord" => "ArrayOfActivityRecord", "ArrayOfActivityType" => "ArrayOfActivityType", "ArrayOfAttribute" => "ArrayOfAttribute", "ArrayOfBase64Binary" => "ArrayOfBase64Binary", "ArrayOfCampaignRecord" => "ArrayOfCampaignRecord", "ArrayOfLeadChangeRecord" => "ArrayOfLeadChangeRecord", "ArrayOfLeadKey" => "ArrayOfLeadKey", "ArrayOfLeadRecord" => "ArrayOfLeadRecord", "ArrayOfLeadStatus" => "ArrayOfLeadStatus", "ArrayOfSyncStatus" => "ArrayOfSyncStatus", "ArrayOfVersionedItem" => "ArrayOfVersionedItem", "paramsGetCampaignsForSource" => "paramsGetCampaignsForSource", "paramsGetLead" => "paramsGetLead", "paramsGetLeadActivity" => "paramsGetLeadActivity", "paramsGetLeadChanges" => "paramsGetLeadChanges", "paramsGetMultipleLeads" => "paramsGetMultipleLeads", "paramsListOperation" => "paramsListOperation", "paramsRequestCampaign" => "paramsRequestCampaign", "paramsSyncLead" => "paramsSyncLead", "paramsSyncMultipleLeads" => "paramsSyncMultipleLeads", "successGetCampaignsForSource" => "successGetCampaignsForSource", "successGetLead" => "successGetLead", "successGetLeadActivity" => "successGetLeadActivity", "successGetLeadChanges" => "successGetLeadChanges", "successGetMultipleLeads" => "successGetMultipleLeads", "successListOperation" => "successListOperation", "successRequestCampaign" => "successRequestCampaign", "successSyncLead" => "successSyncLead", "successSyncMultipleLeads" => "successSyncMultipleLeads"); } /** * Client for Marketo SOAP API. * */ class mktSampleMktowsClient { // Change this vale to true to enable debug output. const DEBUG = false; const CLIENT_TZ = 'America/Los_Angeles'; const MKTOWS_USER_ID = 'USER_ID_FROM_MARKETO_WEBSITE'; const MKTOWS_SECRET_KEY = 'SECRET_KEY_FROM_MARKETO_WEBSITE'; const MKTOWS_NAMESPACE = 'http://www.marketo.com/mktows/'; protected $accessKey; protected $secretKey; /** * @var SoapClient */ protected $soapClient; public function __construct($accessKey, $secretKey, $soapEndPoint) { $this->accessKey = $accessKey; $this->secretKey = $secretKey; $options = array("connection_timeout" => 20, "location" => $soapEndPoint); if (self::DEBUG) { $options["trace"] = true; } $wsdlUri = $soapEndPoint . '?WSDL'; $this->soapClient = new SoapClient($wsdlUri, $options); } private function _getAuthenticationHeader() { $dtzObj = new DateTimeZone(self::CLIENT_TZ); $dtObj = new DateTime('now', $dtzObj); $timestamp = $dtObj->format(DATE_W3C); //$timestamp = '2009-01-27T15:53'; $encryptString = $timestamp . $this->accessKey; $signature = hash_hmac('sha1', $encryptString, $this->secretKey); //echo "encrypt: $encryptString\n"; //echo "key: {this->secretKey}\n"; //echo "signature: $signature\n"; $attrs = new stdClass(); $attrs->mktowsUserId = $this->accessKey; $attrs->requestSignature = $signature; $attrs->requestTimestamp = $timestamp; $soapHdr = new SoapHeader(self::MKTOWS_NAMESPACE, 'AuthenticationHeader', $attrs); return $soapHdr; } public function getLead($keyType, $keyValue) { $retLead = null; $leadKey = new LeadKey(); $leadKey->keyType = $keyType; $leadKey->keyValue = $keyValue; $params = new paramsGetLead(); $params->leadKey = $leadKey; $options = array(); $authHdr = $this->_getAuthenticationHeader(); try { $success = $this->soapClient->__soapCall('getLead', array($params), $options, $authHdr); if (self::DEBUG) { $req = $this->soapClient->__getLastRequest(); echo "RAW request:\n$req\n"; $resp = $this->soapClient->__getLastResponse(); echo "RAW response:\n$resp\n"; } if (isset($success->result)) { if ($success->result->count > 1) { // Is this okay? If not, raise exception } if (isset($success->result->leadRecordList->leadRecord)) { $leadRecList = $success->result->leadRecordList->leadRecord; if (!is_array($leadRecList)) { $leadRecList = array($leadRecList); $count = count($leadRecList); if ($count > 0) { $retLead = $leadRecList[$count-1]; } } } } } catch (SoapFault $ex) { $ok = false; $errCode = 1; $faultCode == null; if (!empty($ex->detail->serviceException->code)) { $errCode = $ex->detail->serviceException->code; } if (!empty($ex->faultCode)) { $faultCode = $ex->faultCode; } switch ($errCode) { case mktWsError::ERR_LEAD_NOT_FOUND: $ok = true; $success = false; break; default: } if (!$ok) { if ($faultCode != null) { if (strpos($faultCode, 'Client')) { // This is a client error. Check the other codes and handle. } else if (strpos($faultCode, 'Server')) { // This is a server error. Call Marketo support with details. } else { // W3C spec has changed :) // But seriously, Call Marketo support with details. } } else { // Not a good place to be. } } } catch (Exception $ex) { $msg = $ex->getMessage(); $req = $this->soapClient->__getLastRequest(); echo "Error occurred for request: $msg\n$req\n"; var_dump($ex); exit(1); } return $retLead; } public function listOperation($listKey, $listOperation, $leadKeys, $strict) { // Build API params $params = new paramsListOperation(); $params->listOperation = $listOperation; $params->listKey = new ListKey(); $params->listKey->keyType = $listKey['keyType']; $params->listKey->keyValue = $listKey['keyValue']; $leadList = new ArrayOfLeadKey(); $leadList->leadKey = array(); foreach ($leadKeys as $key) { $leadKey = new LeadKey(); $leadKey->keyType = $key['type']; $leadKey->keyValue = $key['value']; $leadList->leadKey[] = $leadKey; } $params->listMemberList = $leadList; $params->strict = $strict; $options = array(); $authHdr = $this->_getAuthenticationHeader(); try { $success = $this->soapClient->__soapCall('listOperation', array($params), $options, $authHdr); $resp = $this->soapClient->__getLastResponse(); if (self::DEBUG) { $req = $this->soapClient->__getLastRequest(); echo "RAW request:\n$req\n"; $resp = $this->soapClient->__getLastResponse(); echo "RAW response:\n$resp\n"; } } catch (SoapFault $ex) { $ok = false; $errCode = 1; $faultCode == null; if (!empty($ex->detail->serviceException->code)) { $errCode = $ex->detail->serviceException->code; } if (!empty($ex->faultCode)) { $faultCode = $ex->faultCode; } switch ($errCode) { case mktWsError::ERR_LIST_NOT_FOUND: break; default: } if (!$ok) { if ($faultCode != null) { if (strpos($faultCode, 'Client')) { // This is a client error. Check the other codes and handle. } else if (strpos($faultCode, 'Server')) { // This is a server error. Call Marketo support with details. } else { // W3C spec has changed :) // But seriously, Call Marketo support with details. } } else { // Not a good place to be. } } } catch (Exception $ex) { $msg = $ex->getMessage(); $req = $this->soapClient->__getLastRequest(); echo "Error occurred for request: $msg\n$req\n"; var_dump($ex); exit(1); } return $success; } public function syncLead($key, $attrs) { // Build array of Attribute objects $attrArray = array(); foreach ($attrs as $attrName => $attrValue) { $a = new Attribute(); $a->attrName = $attrName; $a->attrValue = $attrValue; $attrArray[] = $a; } $aryOfAttr = new ArrayOfAttribute(); $aryOfAttr->attribute = $attrArray; // Build LeadRecord $leadRec = new LeadRecord(); $leadRec->leadAttributeList = $aryOfAttr; // Set the unique lead key. if (is_numeric($key)) { $leadRec->Id = $key; // Marketo system ID. } else { $leadRec->Email = $key; // TODO - Add email format validation - should be SMTP email address. } // Build API params $params = new paramsSyncLead(); $params->leadRecord = $leadRec; $params->returnLead = false; // Don't return the full lead record - just the ID. $options = array(); $authHdr = $this->_getAuthenticationHeader(); try { $success = $this->soapClient->__soapCall('syncLead', array($params), $options, $authHdr); $resp = $this->soapClient->__getLastResponse(); if (self::DEBUG) { $req = $this->soapClient->__getLastRequest(); echo "RAW request:\n$req\n"; $resp = $this->soapClient->__getLastResponse(); echo "RAW response:\n$resp\n"; } } catch (SoapFault $ex) { $ok = false; $errCode = 1; $faultCode == null; if (!empty($ex->detail->serviceException->code)) { $errCode = $ex->detail->serviceException->code; } if (!empty($ex->faultCode)) { $faultCode = $ex->faultCode; } switch ($errCode) { case mktWsError::ERR_LEAD_SYNC_FAILED: // Retry once and handle error if retry fails. break; default: } if (!$ok) { if ($faultCode != null) { if (strpos($faultCode, 'Client')) { // This is a client error. Check the other codes and handle. } else if (strpos($faultCode, 'Server')) { // This is a server error. Call Marketo support with details. } else { // W3C spec has changed :) // But seriously, Call Marketo support with details. } } else { // Not a good place to be. } } } catch (Exception $ex) { $msg = $ex->getMessage(); $req = $this->soapClient->__getLastRequest(); echo "Error occurred for request: $msg\n$req\n"; var_dump($ex); exit(1); } return $success; } public function getCampaignsForSource() { $retList = null; $params = new paramsGetCampaignsForSource(); $params->source = 'MKTOWS'; // We want campaigns configured for access through the SOAP API $authHdr = $this->_getAuthenticationHeader(); try { $success = $this->soapClient->__soapCall('getCampaignsForSource', array($params), $options, $authHdr); if (self::DEBUG) { $req = $this->soapClient->__getLastRequest(); echo "RAW request:\n$req\n"; $resp = $this->soapClient->__getLastResponse(); echo "RAW response:\n$resp\n"; } if (isset($success->result->returnCount) && $success->result->returnCount > 0) { if (isset($success->result->campaignRecordList->campaignRecord)) { $retList = array(); // campaignRecordList is ArrayOfCampaignRecord from WSDL $campRecList = $success->result->campaignRecordList->campaignRecord; // Force to array when one 1 item is returned (quirk of PHP SOAP) if (!is_array($campRecList)) { $campRecList = array($campRecList); } // $campRec is CampaignRecord from WSDL foreach ($campRecList as $campRec) { $retList[$campRec->name] = $campRec->id; } } } } catch (SoapFault $ex) { if (self::DEBUG) { $req = $this->soapClient->__getLastRequest(); echo "RAW request:\n$req\n"; $resp = $this->soapClient->__getLastResponse(); echo "RAW response:\n$resp\n"; } $ok = false; $errCode = !empty($ex->detail->serviceException->code)? $ex->detail->serviceException->code : 1; $faultCode = !empty($ex->faultCode) ? $ex->faultCode : null; switch ($errCode) { case mktWsError::ERR_CAMP_NOT_FOUND: // Handle error for campaign not found break; default: // Handle other errors } if (!$ok) { if ($faultCode != null) { if (strpos($faultCode, 'Client')) { // This is a client error. Check the other codes and handle. } else if (strpos($faultCode, 'Server')) { // This is a server error. Call Marketo support with details. } else { // W3C spec has changed :) // But seriously, Call Marketo support with details. } } else { // Not a good place to be. } } } catch (Exception $ex) { $msg = $ex->getMessage(); $req = $this->soapClient->__getLastRequest(); echo "Error occurred for request: $msg\n$req\n"; var_dump($ex); exit(1); } return $retList; } public function requestCampaign($campId, $leadEmail) { $retStat = false; $leadKey = new LeadKey(); $leadKey->keyType = 'IDNUM'; $leadKey->keyValue = $leadEmail; $leadList = new ArrayOfLeadKey(); $leadList->leadKey = array($leadKey); $params = new paramsRequestCampaign(); $params->campaignId = $campId; $params->leadList = $leadList; $params->source = 'MKTOWS'; $authHdr = $this->_getAuthenticationHeader(); try { $success = $this->soapClient->__soapCall('requestCampaign', array($params), $options, $authHdr); if (self::DEBUG) { $req = $this->soapClient->__getLastRequest(); echo "RAW request:\n$req\n"; $resp = $this->soapClient->__getLastResponse(); echo "RAW response:\n$resp\n"; } if (isset($success->result->success)) { $retStat = $success->result->success; } } catch (SoapFault $ex) { $ok = false; $errCode = !empty($ex->detail->serviceException->code)? $ex->detail->serviceException->code : 1; $faultCode = !empty($ex->faultCode) ? $ex->faultCode : null; switch ($errCode) { case mktWsError::ERR_LEAD_NOT_FOUND: // Handle error for campaign not found break; default: // Handle other errors } if (!$ok) { if ($faultCode != null) { if (strpos($faultCode, 'Client')) { // This is a client error. Check the other codes and handle. } else if (strpos($faultCode, 'Server')) { // This is a server error. Call Marketo support with details. } else { // W3C spec has changed :) // But seriously, Call Marketo support with details. } } else { // Not a good place to be. } } } catch (Exception $ex) { $msg = $ex->getMessage(); $req = $this->soapClient->__getLastRequest(); echo "Error occurred for request: $msg\n$req\n"; var_dump($ex); exit(1); } return $retStat; } /** * Enter description here... * * @param string $leadEmail Lead email * @param string $listName Name of static list * @param string $sinceTimestamp Some valid PHP time string like 2009-12-25 01:00:00 * @param int $lastId ID of last activity */ public function wasLeadAddedToListSince($leadId, $listName, $sinceTimestamp, $lastId) { $wasAdded = false; $actRec = null; $leadKey = new LeadKey(); $leadKey->keyType = 'IDNUM'; $leadKey->keyValue = $leadId; $params = new paramsGetLeadActivity(); $params->leadKey = $leadKey; $actTypes = array(); $actTypes[] = 'AddToList'; $actArray = new ArrayOfActivityType(); $actArray->activityType = $actTypes; $filter = new ActivityTypeFilter(); $filter->includeTypes = $actArray; $params->activityFilter = $filter; $startPos = new StreamPosition(); $dtzObj = new DateTimeZone(self::CLIENT_TZ); // Use the correct time zone ! $dtObj = new DateTime($sinceTimestamp, $dtzObj); $startPos->oldestCreatedAt = $dtObj->format(DATE_W3C); $params->startPosition = $startPos; $params->batchSize = 100; $doPage = true; while($doPage) { $authHdr = $this->_getAuthenticationHeader(); try { $success = $this->soapClient->__soapCall('getLeadActivity', array($params), $options, $authHdr); if (self::DEBUG) { $req = $this->soapClient->__getLastRequest(); echo "RAW request:\n$req\n"; $resp = $this->soapClient->__getLastResponse(); echo "RAW response:\n$resp\n"; } if (isset($success->leadActivityList)) { // leadActivityList is LeadActivityList in WSDL $result = $success->leadActivityList; if ($result->returnCount > 0) { // actRecList is ArrayOfActivityRecord from WSDL $actRecList = $result->activityRecordList; // Force to array when one 1 item is returned (quirk of PHP SOAP) if (!is_array($actRecList)) { $actRecList = array($actRecList); } foreach ($actRecList as $actRec) { if ($actRec->id > $lastId && $actRec->mktgAssetName == $listName) { $wasAdded = true; break 2; } } $newStartPos = $success->leadActivityList->newStartPosition; $params->startPosition = $newStartPos; } else { $doPage = false; } } } catch (SoapFault $ex) { $doPage = false; $ok = false; $errCode = !empty($ex->detail->serviceException->code)? $ex->detail->serviceException->code : 1; $faultCode = !empty($ex->faultCode) ? $ex->faultCode : null; switch ($errCode) { case mktWsError::ERR_LEAD_NOT_FOUND: // Handle error for lead not found break; default: // Handle other errors } if (!$ok) { if ($faultCode != null) { if (strpos($faultCode, 'Client')) { // This is a client error. Check the other codes and handle. } else if (strpos($faultCode, 'Server')) { // This is a server error. Call Marketo support with details. } else { // W3C spec has changed :) // But seriously, Call Marketo support with details. } } else { // Not a good place to be. } } break; } catch (Exception $ex) { $msg = $ex->getMessage(); $req = $this->soapClient->__getLastRequest(); echo "Error occurred for request: $msg\n$req\n"; var_dump($ex); exit(1); } } return array($wasAdded, $actRec); } } class mktWsError { const ERR_SEVERE_INTERNAL_ERROR = 10001; const ERR_INTERNAL_ERROR = 20011; const ERR_REQUEST_NOT_UNDERSTOOD = 20012; const ERR_ACCESS_DENIED = 20013; const ERR_AUTH_FAILED = 20014; const ERR_REQUEST_LIMIT_EXCEEDED = 20015; const ERR_REQ_EXPIRED = 20016; const ERR_INVALID_REQ = 20017; const ERR_BAD_ENCODING = 20018; const ERR_UNSUPPORTED_OP = 20019; const ERR_LEAD_KEY_REQ = 20101; const ERR_LEAD_KEY_BAD = 20102; const ERR_LEAD_NOT_FOUND = 20103; const ERR_LEAD_DETAIL_REQ = 20104; const ERR_LEAD_ATTRIB_BAD = 20105; const ERR_LEAD_SYNC_FAILED = 20106; const ERR_ACTIVITY_KEY_BAD = 20107; const ERR_PARAMETER_REQ = 20109; const ERR_PARAMETER_BAD = 20110; const ERR_LIST_NOT_FOUND = 20111; const ERR_CAMP_NOT_FOUND = 20113; const ERR_BAD_PARAMETER = 20114; const ERR_BAD_STREAM_POS = 20122; const ERR_STREAM_AT_END = 20123; } /****************************************************************************** * Entry point *****************************************************************************/ error_reporting(0); # Our form contains four fields: firstname, lastname, creditunion and email $error = false; // this variable was used for error tracking in case a call to marketo web service failed # If email field is set, the form was submitted and we need to process it $isPostback = isset($_REQUEST['email']); if ($isPostback) { // Setup the client # USER_ID and SECRET_KEY need to be created through Marketo web interface and pasted on lines 999 and 1000 of this file $accessKey = mktSampleMktowsClient::MKTOWS_USER_ID; $secretKey = mktSampleMktowsClient::MKTOWS_SECRET_KEY; // !!! SET END POINT TO YOUR CUSTOMER SPECIFIC URL, CAN BE FOUND IN MARKETO ADMIN INTERFACE !!! $soapEndPoint = 'https://na-n.marketo.com/soap/mktows/1_7'; # a mktSampleMktowsClient object is created to make all the web service calls $client = new mktSampleMktowsClient($accessKey, $secretKey, $soapEndPoint); # syncLead call either creates a lead with a given email or updates an existing lead $result = $client->syncLead($_REQUEST['email'], array('Company'=>$_REQUEST['creditunion'], 'FirstName'=>$_REQUEST['firstname'], 'LastName'=>$_REQUEST['lastname'])); if (isset($result->result) && is_numeric($result->result->leadId)) { # if previous syncLead call was successfull and $result->result contains a valid numeric lead id we add the lead to a list of our choice # in this case it's a SomeListName list, the list name would be exactly as it is in the Marketo admin interface $result = $client->listOperation(array('keyType'=>'MKTOLISTNAME', 'keyValue'=>'SomeListName'), 'ADDTOLIST', array(array('type'=>'IDNUM','value'=>$result->result->leadId)), FALSE); } else { $error = true; } } /* These are the standard dynamic attributes in the LeadRecord: "AnnualRevenue" "AnonymousIP" "City" "Company" "ContactCompany" "Country" "DateofBirth" "DoNotCall" "DoNotCallReason" "Email" "Fax" "FirstName" "Industry" "InferredCompany" "InferredCountry" "IsLead" "LastName" "LeadPerson" "LeadRole" "LeadScore" "LeadSource" "LeadStatus" "MainPhone" "MiddleName" "MobilePhone" "NumberOfEmployees" "OriginalReferrer" "OriginalSearchEngine" "OriginalSearchPhrase" "OriginalSourceInfo" "OriginalSourceType" "PersonPrimaryLeadInterest" "PersonType" "Phone" "PostalCode" "Rating" "RegistrationSourceInfo" "RegistrationSourceType" "Salutation" "SICCode" "Site" "State" "Street" "Title" "Unsubscribed" "UnsubscribedReason" "Website" */ ?>