jump to navigation

It’s been awhile… July 25, 2008

Posted by mmoriar1 in Uncategorized.
2 comments

It’s been about 3 weeks since my last post.  I’ve been slacking in the documentation part of my project I suppose.  Oops 🙂

I’ve done a whole lot in the past 3 weeks, as expected of me.  What I’ve done is implement pages for Triggered Send Definition CRUD (Create Retrieve Update Delete), Triggered Send Definition Tracking data retrieval, ListSubscriber Retrieval, ImportDefinition Creation and Perform, EmailSendDefinition Creation and Perform, List CRUD, Group RUD, Data Extension CD, to name a few.

What I’ll go over in this post is a few nuances which, if known, will help coding the above Web Services calls.

  • Caveats of sending a triggered send via Web Services
  • Retrieving Triggered Send Definitions
  • How to use ListSubscriber to get subs on a list or lists for a sub
  • Details around the DataExtensionObject

One major caveat of sending a triggered send through Web Services is that you must make sure that the subscriber’s required attributes are populated prior to sending a triggered send to said subscriber.  for example, if Last Name was a required subscriber attribute, and I tried to send to a subscriber without a last name attribute being populated, I would get the error: “Unable to queue Triggered Send request.  There are no valid subscribers.”

Another big caveat that is mostly common sense is that if AutoAddSubscribers and/or AutoUpdatesubscribers is/are equal to true then the TriggeredSendDefinition List must be set to a valid List.  This is so that the subscriber can be added/updated on a list if desired.

When retrieving Triggered Send Definitions (as well as a few other objects like Import Definitions, etc.) deleted triggered sends will be retrieved.  This is because, although they are labeled as Deleted in the ExactTarget system, they are still IN the system and will be retrieved as such.  You won’t be able to send or modify the Definition (or other object) in any way, but nonetheless it is there and might confuse someone who doesn’t expect to see a deleted TSD in their list of Definitions.

Working with ListSubscriber objects is pretty straightforward.  Below are two code snippets that are fairly useful:

Get all lists that a subscriber is on:

String usermm = Session[“Curr_User_Name”].ToString();
String mmpass = Session[“Curr_User_Pass”].ToString();
PartnerAPIWse integrationFramework = CreatePartnerAPI(usermm, mmpass);

SimpleFilterPart sfp = new SimpleFilterPart();
sfp.Property = “SubscriberKey”;
sfp.SimpleOperator = SimpleOperators.equals;
sfp.Value = new string[] { “SubscriberKey” }; //put the desired subkey here

RetrieveRequest listsub_request = new RetrieveRequest();
listsub_request.ObjectType = “ListSubscriber”;
listsub_request.Filter = sfp;

string[] ls_props = new string[] { “ListID”, “SubscriberKey”, “Status” };

listsub_request.Properties = ls_props;

APIObject[] results;
string status = “”;
string requestID = “”;
status = integrationFramework.Retrieve(listsub_request, out requestID, out results);

Get all subscribers on a list:

String usermm = Session[“Curr_User_Name”].ToString();
String mmpass = Session[“Curr_User_Pass”].ToString();
PartnerAPIWse integrationFramework = CreatePartnerAPI(usermm, mmpass);

SimpleFilterPart sfp = new SimpleFilterPart();
sfp.Property = “ListID”;
sfp.SimpleOperator = SimpleOperators.equals;
sfp.Value = new string[] { “1234” }; //put the desired listid here

RetrieveRequest listsub_request = new RetrieveRequest();
listsub_request.ObjectType = “ListSubscriber”;
listsub_request.Filter = sfp;

string[] ls_props = new string[] { “Status”, “SubscriberKey”, “ListID” };

listsub_request.Properties = ls_props;

APIObject[] results;
string status = “”;
string requestID = “”;
status = integrationFramework.Retrieve(listsub_request, out requestID, out results);

Finally, I’ve been able to Create (but not successfully delete yet, more details to come) DataExtensionObjects.  DataExtensionObjects correspond to individual records in a Data Extension table.  Here is some sample code on how to do this:

// Instantiate the API
String usermm = Session[“Curr_User_Name”].ToString();
String mmpass = Session[“Curr_User_Pass”].ToString();
PartnerAPIWse integrationFramework = CreatePartnerAPI(usermm, mmpass);

DataExtensionObject deo = new DataExtensionObject();
deo.Name = “Name”; //the name of the data extension
deo.CustomerKey = “Key”; //the external key of the data extension

deo.Properties = new APIProperty[numFields]; //numfields is the number of fields which exist in the data extension
for (int i = 0; i < numFields; i++)
{
deo.Properties[i] = new APIProperty();
deo.Properties[i].Name = “Name”; //enter the name of the field here
deo.Properties[i].Value = “Value”; // enter the desired value for the field here
}

string status = “”;
string requestID = “”;
CreateResult[] results = integrationFramework.Create(new CreateOptions(), new APIObject[] { deo }, out requestID, out status);

I’m going to start documenting a lot more soon, expect more frequent updates once my coding starts to slow up.

Thanks,

Michael

Advertisements

Timeout? Nope. TimeIN. July 1, 2008

Posted by mmoriar1 in Uncategorized.
add a comment

Since last time, I’ve completed retrieval of tracking events and minimal retrieval of triggered sends.  Some things I’ve encountered that I will talk about in this post:

  • The timeout setting on the PartnerAPIWse object is quite important and crucial to performing many API calls
  • The AJAX calendar extender is a very sleek way for the user to input dates
  • Retrieving tracking events is fairly straightforward, and when retrieving more than 2500 objects, you must check the call’s status for “MoreDataAvailable”
  • It’s much much quicker to retrieve tracking events in bulk and then filter on subscriber locally then to use multiple small retrieves and have the ExactTarget system filter on subscriber key

First I’ll talk about the timeout setting on the PartnerAPIWse object.  Before finding this setting, my API calls would timeout if I was operating on more than ~200 object.  The SOAP envelope was just too big and ExactTarget was dropping it after 90 seconds (the default setting).  After setting the timeout higher, however, I’ve been able to perform create/retrieve/update/delete calls on 12000+ subscriber objects.  So that’s the key to performing calls on a greater number of objects:

PartnerAPIWse integrationFramework = CreatePartnerAPI(usermm, mmpass);
integrationFramework.Timeout = 500000;

You’ve probably used a calendar extender before.  It’s what most travel websites use for their date input fields.  The one that is used in the ASP.NET AJAX Toolkit is pretty much the same as those.  It’s fully customizable, and it’s very easy to use and install.  Link: http://www.asp.net/learn/ajax-videos/video-124.aspx .

When retrieving more than 2500 records, you must keep inspecting the status of the API call to see if it is “MoreDataAvailable”.  Also, I’ve discovered that performing API calls on larger chunks of objects is more efficient than breaking the large group into smaller chunks.  For example, when I created 12000+ subscribers by breaking it up and creating 100 at a time, the total creation time was 28 minutes.  When I created 2500 (the limit) at a time, the creation time was 13 minutes.  These results were fairly repeatable.  Here is some sample code for retrieving all of the clickevents for a send (may total in the millions):

do
{
if (status == “MoreDataAvailable”) request.ContinueRequest = requestID;
status = partnerAPI.Retrieve(request, out requestID, out results);
if (results.Length > 0)
{
Console.WriteLine(“Found {0} ClickEvents”, results.Length.ToString());
blnFoundData = true;
createTSVFile(results);
}
else
{
Console.WriteLine(“No ClickEvents found. Status = ” + status);
}
} while (status == “MoreDataAvailable”); // Get additional results

If I remember anything else, I’ll post it here.

Until next time,

Mike