How to update a Data Extension in ExactTarget with PHP

ExactTarget's documentation leaves something to be desired... It took me a while to figure this out, and it came mostly out of trial and error or other users like me who posted tutorials. So I wanted to pay it forward by posting my experience here, in hopes that it will help someone. The tutorial is below, but the entire directory is also available in my downloads section, at the bottom of this page, or in my github repository.

So if you’re struggling with how to create your own web form that updates a Data Extension, this tutorial is for you.

I’ve made it extremely easy for you by putting variables for your account name, etc at the top.

FIRST
We’ll start of by creating a basic web form. This has any and all fields you’ll need. Don’t worry about ids or classes. You can add them if you want, but you don’t need to. Just make sure each field has a name. For the code here to work, make sure your field names match exactly what you have set up in ExactTarget.

Here is the basic form. This is just html.

<form id="newsletter" action="handle-et-data.php"  name="subscribeForm" method="post" novalidate>
    <input type="hidden" name="San Diego Monthly Newsletter" value="true" id="leisure">
    <input type="hidden" id="pageURL" name="Signup URL" value="http://preview.sandiego.org/newsletter.aspx">
    <label for="email">Email<sup>*</sup></label>
    <input type="text" name="Email Address" id="emailInput">
    <label for="zipcode">Zipcode<sup>*</sup></label>
    <input type="text" name="United States Zip Code" id="zipcode">
    <label for="first_name">First Name</label>
    <input type="text" name="First Name" id="first_name">
    <label for="last_name">Last Name</label>
    <input type="text" name="Last Name" id="last_name">
    <label for="state">State</label>
    <select name="US State" id="state" size="1">
    <option selected="selected">Select a State</option>
    <option value="AL">Alabama</option>
    <option value="MS">Mississippi</option>
    <option value="OH">Ohio</option>
    <option value="WY">Wyoming</option>
    </select>
    <label for="first_name">Birthday Month and Day (MM/DD)</label>
    <input type="text" value="01/01" name="Birthday" id="datepicker" class="hasDatepicker">
    <p>Please select which content you'd like to receive.</p>
    <ul>
        <li><input type="checkbox" id="artsculture" value="true" name="Arts and Culture">
        <label>Arts and Culture</label></li>
        <li><input type="checkbox" id="diningnightlife" value="true" name="Dining and Nightlife">
        <label>Dining and Nightlife</label></li>
        <li><input type="checkbox" id="casinos" value="true" name="Casinos">
        <label>Casinos</label></li>
    </ul>
    <input type="submit" id="submit-button" value="Submit">
</form>

See a demo HERE.

You may notice that the form action calls a php file (action="handle-et-data.php"). That file processes the form fields.

To make this easier we'll build the PHP step by step. First get all of the ExactTarget particulars out of the way such as login, included files, etc.

<?php 
  require('00-Includes/exacttarget_soap_client.php');
  $wsdl = 'https://webservice.s4.exacttarget.com/etframework.wsdl';
  $etusername = 'your_et_username';//Enter the username you use to login to Exact Target
  $etpassword = 'your_et_password';//Enter the password you use to login to Exact Target

For the most up to date exacttarget_soap_client.php file check out ExactTarget's Git page. For sake of ease, I'll include it here as well. Your link for $wsdl may be slightly different. Check your admin account for the s4, s5, or s6 instance you are on.

Next we'll build an array of all of your field names. Change the names here to match each and every field name you have in your ExactTarget Data Extension EXACTLY. NOTE: You should also have a form field or input for each one of these.

$fieldNames = array(
	'Email Address',
	'First Name',
	'Last Name',
	'United States Zip Code',
	'State',
	'Country',
	'Birthday',
	'Arts and Culture',
	'Dining and Nightlife',
	'Casinos',
	'Signup URL'
);

Then we'll take those field names a build another array with key/value pairs. You'll see why later.

$mySub = array();
foreach($fieldNames as $field){
	if(isset($_POST[str_replace(' ','_',$field)])){
		$mySub[$field]=$_POST[str_replace(' ','_',$field)];
	}
}

Then we'll start building our function

function addUpdateDE($mySub,$client){
	  //validate email address and make sure they entered a zip code
	  if (!filter_var($mySub['Email Address'], FILTER_VALIDATE_EMAIL)) {
		echo 'Please provide a valid email address.';return;
	  } 
	  
	  if($mySub['United States Zip Code'].length<1){
		  echo 'Zip code is required.';return;
	  }

These first two if statements make sure that the email address is valid and that they included the zip code. Sorry, I didn't have a more elegant way of doing this so for your required fields you'll just have to copy and modify.

The next two lines connect to our Data Extensions. Change "Cons-10001" for the external key from your data extension.

    $DE = new ExactTarget_DataExtensionObject();
	  $DE->CustomerKey="Cons-10001"; // unique identifier to the data extension

Then we need to get the keys from the array $mySub and we build a new array called $keys. This is just for setting the Primary Key in your Data Extension, which is most likely your email address.

	  $keys = array_keys($mySub);//make a new array with keys from our fields array
	  
	  /*Update can happen only if you have PrimaryKey column in the Data Extension*/ 
	  $apiPropertyKey = new ExactTarget_APIProperty();
	  $apiPropertyKey->Name=$keys[0];  // primary key of the data extension
	  $apiPropertyKey->Value=$mySub[$keys[0]]; // value of the primary key for the row we want to add/update
	  $DE->Keys[] = $apiPropertyKey; // add primary key field to the data exension

Next we'll loop through all the other fields and match them to the inputs from the html form.

	  /*Update other fields*/
	  $i=0;
	  $apiProperty = array();
	  foreach($mySub as $key => $value){
		  $apiProperty[$i] =new ExactTarget_APIProperty();
		  $apiProperty[$i]->Name=$key; // field we want to add/update
		  $apiProperty[$i]->Value=$value; // new value for LastName
		  $i++;
	  }//loop end
	  $DE->Properties=$apiProperty;

This is some Exact Target $hit, don't touch it!

 $object1 = new SoapVar($DE, SOAP_ENC_OBJECT, 'DataExtensionObject', "http://exacttarget.com/wsdl/partnerAPI");
	  
	  /*% Create the ExactTarget_SaveOption Object */ 
	  $saveOption = new ExactTarget_SaveOption();                
	  //$saveOption->PropertyName=$DE;
	  $saveOption->PropertyName="DataExtensionObject";
	  $saveOption->SaveAction=ExactTarget_SaveAction::UpdateAdd; // set the SaveAction to add/update

	  // Apply options and object to request and perform update of data extension
	  $updateOptions = new ExactTarget_UpdateOptions();
	  $updateOptions->SaveOptions[] = new SoapVar($saveOption, SOAP_ENC_OBJECT, 'SaveOption', "http://exacttarget.com/wsdl/partnerAPI");
	  $request->Options = new SoapVar($updateOptions, SOAP_ENC_OBJECT, 'UpdateOptions', "http://exacttarget.com/wsdl/partnerAPI");
	  $request = new ExactTarget_CreateRequest();
	  $request->Options = $updateOptions;
	  $request->Objects = array($object1);
	  $results = $client->Update($request);

Ok finally our error message handling and closing braces

	  $status = $results->OverallStatus;
	  if($status === "OK"){
		  echo "Thank you for signing up. Be on the lookout for hot San Diego news!";	
	  }else{
		  echo "An unknown error occurred, please try again.";
	  }
}

Now if you've got this working you'll notice that it just goes to a white page and outputs a string of text. Not very exciting. If you want to get a little fancier you can add some ajax to your form page to retrieve the response so you don't have to leave the page.

Put this in your head tag.

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script type="text/javascript">
$("document").ready(function(){
	
var myURL = document.URL;
var myField = document.getElementById("pageURL");
myField.value = myURL;

$("#newsletter").submit(function(event){
    event.preventDefault();
    formData = $(this).serialize();
    $.ajax({
      type: "POST",
      dataType: "text",
      url: "handle-et-data.php", //Relative or absolute path to php file
      data: formData
	  }).done(function(data) {
		$('#formalert').fadeIn(200).text(data).delay(2000).fadeOut(200);
      });
    return false;
  });
});
</script>

One thing I haven't mentioned is the signup url. We put little signup boxes all over our site, and we wanted to know which page a user signed up on, just in case we wanted to act on that information later. I have a field named "Signup URL" both in ExactTarget and in my form. The three lines of javascript at the top of the code block above grab the url and set that input field to the value. If you don't need this just delete those three lines.

In my next tutorial I'll cover how to write some jQuery code that will send you an email right after a user enters their email address and then moves on to the next box. This was useful to me for testing... I wanted to make sure the form was actually working, and that users were making their way into the Data Extension.