Skip navigation
All Places > Marketo Whisperer: Implementation Tips > 2015 > October
2015

While the Marketo form builder is quite powerful, there are some edge cases where it doesn't produce quite the result that you're looking for.  A common request is to reposition fields after the progressive profiling box, which is a capability that isn't currently available natively.  Fortunately, with some javascript tweaks, we can reposition fields freely.  Let's take a look at the code:

/*

jQuery must be loaded on the page

use moveMktoField to position the field designated by FieldName relative to the field designated by pivotName

*/

 

 

function moveMktoField(fieldName, pivotName, beforeOrAfter){

  //find the label element for the field which we want to move

  var labelForFieldToMove = $('[for="' + fieldName + '"]');

  //find the label element for the field we want to position relative to

  var labelForPivot = $('[for="' + pivotName + '"]');

  //get the mktoFormRow parent of each

  var fieldToMove = getParentWithClass(labelForFieldToMove, "mktoFormRow");

  var pivot = getParentWithClass(labelForPivot, "mktoFormRow");

  //insert the field before or after the pivot based on the setting

  if (beforeOrAfter == "before"){

       fieldToMove.insertBefore(pivot);

  } else if (beforeOrAfter == "after"){

       fieldToMove.insertAfter(pivot);

  } else {

       console.log("argument 'beforeOrAfter' must be one of 'before' or 'after'");

       return null;

  }

}

//inserts multiple fields in order where the first in the fields array is adjacent to the pivot, and the last is furthest

function moveMktoFields(fields, pivotName, beforeOrAfter){

  moveMktoField(fields[0], pivotName, beforeOrAfter);

  for ( i = 1; i < array.length; i++ ){

       moveMktoField(fields[i], fields[i - 1], beforeOrAfter);

  }

}

function getParentWithClass(elem, withClass) {

  //Check the parent to see if it has the desired class

  if ( elem.parent().hasClass(withClass) ) {

       return elem.parent();

  } else {

       //if not, call self recursively on the immediate parent

       return (getParentWithClass(elem.parent(), withClass) );

  }

}

 

With the above, we can use the moveMktoField function to reposition one field relative to another.  You can also use moveMktoFields to move the fields as a group when you pass an array of field names to it.  Click here to see a live demo, moving First Name after Last Name.

This series of blog posts is going to review functionality that you can use to be safer when you're building programs directly in production. I'm not suggesting you use all of these every time; there's a level of common sense that you need to deploy here, but it is good to know what options are available.

 

First, let's focus on functionality available across the entire instance.

 

User Permissions

 

Marketo has very granular user permissions that allow you to set up varying roles for users who have less training and/or experience within Marketo. In the Admin section, you can modify user roles so that newer users do not have the ability to take certain actions that have a permanent impact on the database. For example, the following permissions may be restricted:

  • Access, Edit, Approve, or Delete Email Template: Would prevent the user from modifying email templates that may be in use by other groups besides their own
  • Access, Edit, Approve, or Delete Landing Page Template: Would prevent the user from modifying landing page templates that may be in use by other groups besides their own
  • Access, Edit, Approve, or Delete Email, Form, Image, Landing Page, Snippet, Social App: Would prevent the user from modifying the designated asset that may be in use by other groups besides their own
  • Access, Edit, Approve, or Delete Segmentation: Would prevent the user from modifying database segmentations that may be in use by many other groups besides their own
  • Import/Advanced List Import: Would prevent the user from using simple and/or complex list import options that could potentially overwrite data
  • Delete Lead/Person: Would prevent the user from deleting people’s records in the system
  • Edit Person: Would prevent the user from modifying people’s records in the system
  • Run Single Flow Actions: Would prevent the user from running flow actions on an individual, such as changing a field value or adding the person to a list
  • Activate Trigger Campaign: Would prevent the user from turning on any campaigns that run in real time based on the individual’s behavior
  • Approve Email Program: Would prevent the user from launching an email through the email program, which is the program type with the built-in A/B testing functionality that is only used for one-time batch campaigns
  • Delete Marketing Assets: Would prevent the user from deleting local assets within a program
  • Import Program: Would prevent the user from importing programs from sandbox or other instances
  • Schedule Batch Campaign: Would prevent the user from scheduling any campaigns that run on demand or on a schedule based on a predefined list or query


Smart Campaign Limits
In the Admin section, you can modify Smart Campaign settings so that when a new smart campaign is created, a limit is added to the campaign to abort it automatically when more leads exist in the campaign than the limit.

When a smart campaign is created, you can go to the schedule tab to manually override this for a specific campaign.

Using the Smart Campaign limits provides safety in two ways:

  • The limit provides a built-in warning that can prevent people from accidentally emailing a much larger than normal group (e.g. the entire database)
  • The limit adds in a built-in delay, in that individuals who aren’t aware of how to override this functionality would need to go to a more experienced Marketo user for support with this

Many Marketo customers have both a sandbox and a production instance. The sandbox instance has essentially the same standard functionality as a production instance, although it has a built-in restriction that you cannot run a campaign to impact more than 25 leads at a time. You may find that your sandbox does not have some add-on products provisioned, such as Revenue Cycle Analytics, which needs production data in order to be used effectively.

 

In general, we recommend that the sandbox environment be used for testing new code changes and for experimentation with new functionality when this could impact the production data or assets. In particular, we use sandboxes for:

  • Integrations with CRM sandboxes or development environments
  • Testing out custom integrations
  • Testing out the use of new or complex functionality, such as webhooks, web services using the API, and LaunchPoint services

 

We do not recommend building programs in sandbox with the intention of migrating them to production for launch. Testing of programs in sandbox should only be done when using new functionality where you are unclear of the impact and want to experiment. Be aware that there may be variables on production that will impact the program’s performance that are not present in sandbox. In addition, errors may be introduced during the program migration process - user error during the import process or technical issues arising from the import. Consequently, all programs built in sandbox will then need to be re-tested in production following migration, which adds additional time to the launch process. Instead, precautions can be embedded in the building and testing phases to allow you to safely and efficiently build and test directly within the production environment. Those precautions will be the subject of my next few blog posts, so stay tuned!

 

Most of the documentation out there about using engagement programs shows you just dropping emails directly into the stream. However, you can also drop programs into them, and there are many situations where you might want to put your email inside of a program instead of directly into the stream.

 

Why use nested programs?

  • To add additional qualification criteria, e.g. only send this email to people in Canada, even though US people are also in the stream
  • To have conditional choices, e.g. to send a different variation of the email to one sub-group within the stream
  • To include landing pages, forms, or other assets, e.g. webinar invitation that links to a landing page and form for registration
  • Because you want to get multi-touch attribution on nurture email programs
  • To add extra flow steps, such as alert emails, CRM actions, etc.

 

There's a lot of confusion out there about how things work when you put programs inside a nurture. To clear up the confusion and confirm my own experience, I did a lot of testing of all kinds of scenarios, such as:

  • What if a lead got the email directly in the stream and later in the stream, that same email is sent out from within a program?
  • What if the lead got the email from the program first and then the email is standalone in the nurture stream later on?
  • What if the lead already got the email in a previous program and is a member of the next program that sends out the same email?
  • What if I then take that lead out of the program and make them no longer a member?
  • What if they went through that program with one smart campaign and now I create a new smart campaign in that program and add that into the nurture stream instead?
  • What if they aren't a member of the program but they don't qualify for a filter in the smart list?
  • What if I then remove the filter they didn't qualify for?
  • What if the email is in Design Studio? In the program that's inside the nurture? In a different program?

 

The three main conclusions:

 

1. When using nested programs, deciding whether or not to send the email to a person is based on:

    • Program Membership
    • Program ID


What this means is that it does not matter if the person already got the email or not. If the person is a member of the program, they will not get that email. If they are not a member of the program, but have gone through that program ID before in the nurture program, they will not get that email. Only if you are brand new to the program will you get that email.

2. You can reuse an email someone has already gotten if you put it in a new program, regardless of where the email is stored (Design Studio, local to the program, local to another program).

 

The main difference with these options is the reporting and ease of use. When you use a Design Studio email in multiple programs in an engagement stream, the different sends are treated as separate sends in the Engagement Stream Performance report. In the regular Email Performance report, they are treated as the same email and all the metrics are rolled up into one line.

 

3. If you want to resend something, it is always safest to create a new program and smart campaign.

Someone showed me something amazing yesterday that I had no idea you could do in Marketo. I'm guessing I'm not the only one, so I thought I'd share.

 

If you create an editable section in a template and then you want to not use it, it leaves behind a blank white space in your email. This can be really irritating, as it throws off your email design and no one really wants to create a new template every time you leave a section blank.

 

So here's the trick he showed me. Create a new snippet that contains only a blank HTML comment in the HTML source editor. You can leave the text version blank.

 

Then go into your email and replace the editable section you no longer need with this snippet. Bam, section gone with no remaining blank white line in the middle of your email.

Sometimes you want to be able to suppress certain top-level email domains from your communications. If you aren’t suppressing the entire domain (@marketo.com) and you just want to suppress something like .it (all Italian domains), it’s challenging to do this since Marketo does not have an ‘ends with’ filter.

 

One of my customers needed to blacklist all military email addresses, ending in .mil. However, I wanted to make sure we didn’t also blacklist people who just happened to have .mil in their email address, like jon.miller@marketo.com. My solution was to suppress people whose email domains contained .mil but did not contain .mil with any letter or character after it:

 

 

 

I once had a customer who wantedto be able to add the form’s thank you message within the form so that they only needed one landing page instead of having to have a second landing page for the thank you message.

 

In order to make this work properly, we took the following steps:

  • Created the form
  • Created the landing page
  • Placed the form on the landing page
  • Created an HTML element on the landing page and pasted in the code below. This code does the following:
    • Adds an onSuccess handler that hides the form when it is submitted successfully and then gets a hidden div on the page and unhides it
    • Creates the div that is hidden by default and contains the thank you message

 

Here is the example script. You will need to replace the yellow highlighted “app-sj01” with your pod and the yellow highlighted element in the div with the text you want to see.

 

<script src="//app-sj01.marketo.com/js/forms2/js/forms2.js"></script>

<script>

MktoForms2.whenReady(function (form){

  //Add an onSuccess handler

   form.onSuccess(function(values, followUpUrl){

    //get the form's jQuery element and hide it

    form.getFormElem().hide();

    document.getElementById('confirmform').style.visibility = 'visible';

    //return false to prevent the submission handler from taking the lead to the follow up url.

    return false;

  });

});

</script>

<div id="confirmform" style="visibility:hidden;"><p><strong>Thank you. Check your email for details on your request.</strong.</p></div>

 

The text will display on the landing page in the exact position where you place the HTML element, so be sure you edit that in the property sheet. You should also make sure the layer of your HTML element is smaller than the layer for your form. By default, both will be put at Layer 15, so you will be safe if you make your HTML element Layer 14. If you don’t do this, you won’t be able to type in the form field boxes.

 

It is not necessary to change the follow-up type on the form or on the landing page, as the JavaScript will overwrite those settings.

There's some confusion out there on one of the coolest new APIs that Marketo has recently released, the asset API. The asset API enables integration with external content repositories and really raises the bar on the API access to Marketo. It allows you to create, update and delete emails and email templates, approve and unapprove emails, create and update folders and tokens on folders, and even allows you to create, edit and delete at the program level.

 

Wait.. program level? What?

 

It's true. If you look at the Get Folder By ID endpoint you lss see that it expects an ID and a Type... and the type is Folder or Program... what that means is that where you see "folder", you can also think "program"

 

Screen Shot 2015-10-13 at 4.11.02 PM.png

 

So here's the issue. The ID that the API is looking for isnt the "program ID" as you might expect, it's the folder ID of the program, which can be slightly confusing. To get this value use the "Get Folder By Name" endpoint, passing in the program Name, and of course the type of "Program". That will get you the ID you need.

 

Note, this is true for Folders as well as programs!

In Part 1 of this series, I discussed how it was possible to start using the REST API through Boomi with the Boomi HTTP connector, specifically getting the authentication token needed to access the REST API, and storing it in a Process Variable.

Next up, we’ll begin making calls into Marketo, and in this installment, I’ll show you how you can Get Multiple Leads By List ID and next I'll show you how to Remove Leads from List (in bulk, which is tricky).

boomi1

For this installment and the next we’ll be looking at the second highlighted area.

As a review, I’ve included the JSON response we’ll be needing below. Recall that to create a JSON profile in Boomi, all you need to do is create a profile component of type JSON, and click “import” and select the file. Boomi does the rest, extrapolating things like if there should be multiple IDs allowed.

Example JSON for Get Multiple Leads By List ID

{ "requestId": "", "success": true, "nextPageToken": "", "result": [ { "id": 0, "email": "", "firstName": "", "lastName": "" }, { "id": 0, "email": "", "firstName": "", "lastName": "" }, { "id": 0, "email": "", "firstName": "", "lastName": "" } ] }

Step 1: The Get Multiple Leads by List ID

Drop another connector (Get) into your process, using the same connection as defined in the previous article.

Create a new operation called “Get Multiple Leads by List ID” (I’m a stickler for consistency) It’s attributes are as follows
– Request Profile: None (this one uses the request URL)
– Response Profile Type: jSON
– Response Profile: Create a new profile based on the Get Multiple Leads by List ID Response above.

Note that you can change it so that it returns the fields you want, not just the ones listed. Its important to remember that the JSON response profile should really match the list of fields you’re asking for from the REST API, and you should request only the fields you need. In the Process Properties object, we defined a property called “fields” which is a comma separated list of the fields you want REST to return.. and that’s the list that has to match the profile.
Content Type: text/plain (this is just a URL request)
HTTP Method: GET (you look this up in the REST API docs, its always listed)
Resource Path (add 5)
rest/v1/list/
listID (replacement variable)
/leads.json?access_token=
access_token (replacement variable)
&fields=
fields (replacement variable)

booomi2

Then in the parameters tab on the connector, you can enter the variable values, all of which we previously populated into the process properties. In the next section I’ll talk about how you can avoid populating these manually

boomi3

Im going to skip the part of the process where I map the response for Get Multiple Leads by List Id into a flat file profile and stick it on an FTP server because that’s straightforward Boomi functionality.

Part 3 is below!

Using the Marketo REST API with Boomi Part 3: Removing Leads from a Static List

Setting up an automatic export of leads that meet a certain criteria is a very common use case with Marketo. Although this can’t currently be done in the Marketo interface, its pretty straightforward to accomplish using the a 3rd party tool like Dell Boomi, a static list with some data management campaigns, and the Marketo REST API.

The REST API? I thought Boomi didn’t have a Marketo REST API Connector! Well, currently, it doesn’t, but its possible to accomplish the same thing using the HTTP Connector and manually defining the jSON response shapes.

The first step is to set up your Marketo instance to use the REST API as outlined in the REST API Marketo Developer page or simply follow the quick-start REST API guide on the Marketo Developer Blog. I’ll also assume you have access to a Dell Boomi account and have the Boomi skills to create these types of integration processes.

The final process will look like the following, and will include calls to the following Marketo REST API operations, each of which has an associated jSON response shape which can be found on the developer site. To save time, I’ve listed them below

Example JSON for Authentication

{ "access_token": "", "token_type": "", "expires_in": 0, "scope": "" }

Example JSON for Get Multiple Leads By List ID

{ "requestId": "", "success": true, "nextPageToken": "", "result": [ { "id": 0, "email": "", "firstName": "", "lastName": "" }, { "id": 0, "email": "", "firstName": "", "lastName": "" }, { "id": 0, "email": "", "firstName": "", "lastName": "" } ] }

Example JSON for Remove Leads from List

{ "requestId": "", "success": true, "result": [ { "id": 1, "status": "" }, { "id": 2, "status": "", "reasons": [ { "code": "", "message": "" } ] } ] }

boom1

Step 1: Define Properties

Before we start calling REST, it’s important to externalize and encapsulate variables you’ll be using. I’ve defined the following shown below.

boomi2

– ClientID: Get this from your REST Launchpoint Service
– Client Secret: Get this from your REST Launchpoint Service
– AccessToken: We’ll get this from a REST call
– Static ListID: The LIST ID of the static list we’ll operate on. Get this from the URL in Marketo
– Fields: A comma separated list of fields the rest service will get from Marketo for each lead. Mine is “id,email,firstName,lastName”
– IDStringToDelete: Will eventually contain the ID of all the leads in the static list to be used in their removal from the list.
– ActivityTypes: Will be used in Part 2 of this blog, where I expand on this!
– SinceDateTime: Will be used in Part 2 of this blog, where I expand on this!
– PagingToken: Will be used in Part 2 of this blog, where I expand on this!
– Folder – Outgoing: The path to the outgoing folder on the SFTP Server. I will use “/data/outgoing” in this example. It allows us to parameterize the SFTP Operation to make it generic.

Step 2: The Authentication Token

As I mentioned, we’ll place a Connector on the canvas after creating the process with a “No Data” start shape (this is just a personal choice, I like all my connectors looking like British plugs).

The Connector should be configured as follows:

– Connector is an HTTP GET Client
– Connection uses URL: https://123-ABC-456.mktorest.com (note no /rest at the end so that we can use this for REST calls as well as using it to get the identity access token.. and change 123-ABC-456 to the right one for your Marketo instance)
– Operation is “Get oAuth Token” (new!)
– Request Profile = None
– Response Profile = JSON
– New Profile called “Authentication Token Response”
– Content Type: Plain
– HTTP Method: GET
– Resource Path (add 4 without quotation marks): “identity/oAuth/token?grant_type=client_credentials&client_id=”; “ClientID (Replacement variable)”; “&client_secret=”; “ClientSecret (Replacement variable)”
– Set Parameters under Configure —> Parameters —>(+): Set ClientID = Process Property Client ID; Set ClientSecret = Process Property Client Secret

After this, store the success token in the Process Properties “AccessToken” variable as shown, extracting it from the jSON response.

boomi3

The pattern for this step will be repeated for the next steps, but using new operations with different jSON return profiles. In fact, many of the REST calls will be dealt with in the same way with minor changes!

In the next installment we’ll expand on this and get a list of leads from a static list using REST!

For now, run the process, but put a stop shape after your “Set Properties” then run in debug to make sure you see the same token that you see in Marketo. They should match up perfectly!

Next up Using the Marketo REST API with Boomi Part 2: Getting Leads from a Static List

Screen Shot 2015-10-12 at 11.09.19 AM.png

 

Duplicates happens to the best of us, and for a variety of reasons. Perhaps you've merged two instances of Marketo or imported an acquired company's leads into your Salesforce Org, or maybe your sales staff enters new leads rather than updating existing leads. Whatever the cause, Marketo has a service that can address these duplicates and clean up your database, and it's called Automerge.

 

In this article I'll refer to the following

Contacts - Records synched from the CRM's Contact table having a type of "Contact"

Leads - Records synched from the CRM's Lead table having a type of "Lead"

Persons - Marketo only records, not synched to your CRM. These came into Marketo via list upload, entering them in the UI, from the API or through forms submissions.

 

What it IS

Automerge is a solution hosted in AWS created configured and maintained by Marketo Technical Consulting that allows for the de duping of your Marketo instance. It is designed to allow the merging of Contacts and Persons, Leads and Persons and Person to Person duplicates.

 

We can also attempt to merge Leads to Leads with some success, Contacts to Contacts with some success, but we normally cannot merge a Lead and a Contact due to Salesforce API restrictions

 

Automerge Projects

During the project youll work with a Marketo technical consultant to define 4 items listed below which constitute the rules we'll apply to the duplicates you wish to merge.

  1. Definition of a Duplicate - A "duplicate set" is a group of 2 or more leads with the same email. In Marketo, a duplicate is defined as two leads with the same email address. This is typically how we define a duplicate, but we can extend it to include other fields if needed.
  2. Winner Rule
  3. Skip Rules
  4. Field level rules

 

Automerge leverages static lists in your instance that we create for you. Only members of that list and their duplicates (per the definition above) are eligible to be targeted by Automerge, so there's no concern that there will be accidental merging, assuming that we implement any skip rules as needed.

 

Automerge will merge up to 10,000 merge groups per day and can be sold as a one time project or an ongoing process if the duplicates are persistent.

 

So as you can see Automerge can be really powerful for de duplicating in Marketo. If you think this is right for your company, give us a call today for pricing!

This post originally appears on the Marketo Developer's Blog, here.

 

The Marketo REST API may return an exception or error, which, for convenience, we will just call errors from here on out.  Errors can occur at three different levels:

  • HTTP level, these errors are indicated by a 4xx code
  • Response level, these errors are included in the "errors" array of the JSON response
  • Record level, these errors are included in the "result" array of the JSON response, and are indicated on an individual record basis with the "status" field and "reasons" array

 

HTTP Errors

Under normal operating circumstances Marketo should only return two HTTP status errors, 413 Request Entity Too Large, and 414 Request URI Too Long.  These are both recoverable through catching the error, modifying the request and retrying, but with smart coding practices, you should never encounter these in the wild.

Marketo will return 413 if the Request Payload exceeds 1MB, or 10MB in the case of Import Lead.  In most scenarios it unlikely to hit these limits, but adding a check to the size of the request and moving any records which cause the limit to be exceeded to a new request should prevent any circumstances which lead to this error being returned by any endpoints.

 

414 will be returned when the URI of a GET request exceeds 8KiB.  To avoid it, check against the length of your query string to see if it exceeds this limit.  If it does change your request to a POST method, then input your query string as the request body with the additional parameter '_method=GET'.  This forgoes the limitation on URIs.  It's rare to hit this limit in most cases, but is somewhat common when retrieving large batches of records with long individual filter values such as a GUID.

 

Response-Level Errors

Response level errors are present when the "success" parameter of the response is set to false.  Each entry in "errors" has two members, "code" a number, either 6xx or 7xx, and a "message" giving the plaintext reason for the error.  6xx codes always indicate that a request failed completely and were not executed.  An example of this is a 601, "Access token invalid," which is recoverable by re-authenticating and passing the new access token with the request.  7xx errors indicate that the request failed, either because no data was returned, or the request was incorrectly parameterized, such as including an invalid date, or missing a required parameter.

 

Record-Level Errors

Record level errors indicate that an operation could not be completed for an individual record, but the request itself was valid.  These occur within individual record in the "result" array of a response.  The "status" field of these records will be "skipped" and a "reasons" array will be present.  Each reason contains a "code" member, and a "message" member.  The code will always be 1xxx, and the message will indicate why the record was skipped.  An example would be where a Create/Update Leads request has "action" set to "createOnly" but a lead already exists for one of the keys in the submitted records.  This case will return a code of 1005, and a message of "Lead already exists."

 

In the next few posts, we will take a look at recoverable errors, and some examples of how to handle these inside of your code.

Recently, I had to remind one of my clients about the ability to set communication limits in Marketo. We were brainstorming new email and nurture campaigns, and she was concerned about over-communication with leads who qualify for multiple campaigns.

 

So she asked: “How do communication limits work?"

 

There’s some information about this on the community, but it took me some digging around so I’m collecting all that info here for others who might also be curious.

 

The simple answer is: Marketo allows you to set the maximum number of emails a lead will receive per day or per week.

 

A more detailed answer follows in the form of FAQS:

 

  1. How is “per day” and “per week” defined? The per day limit is based on a calendar day from 12 am to 12 am. The per week limit is on a rolling basis from 12 am to 12 am between. (Time zones are defined in your Admin - Location panel).

 

  1. How do you turn on communication limits? You can enable and define communication limits globally in the Admin tab.

  2. Can you override communication limits? You can override global communication limits at an email program level or smart campaign level.

 

  1. What happens if a lead has reached their communication limits? These are the scenarios:

 

  • For plain ole’ scheduled or triggered marketing emails: The lead will NOT receive the email.
  • For operational emails: The lead will still receive the email.
  • For engagement programs: The lead will receive the email in the NEXT cast.
  • For sales insight emails (sent through our Salesforce or MS Dynamics app, not through the Sales Insight email plug-ins for Outlook or Gmail): The lead will receive the email if the email includes an unsubscribe footer. If not, the lead will NOT receive the email.
  • For alerts: The lead - more likely, an internal user - will receive the alert.

 

  1. What emails count towards communication limits?

 

Almost all emails, even operational emails are counted against communication limits. Here’s an idea in the community to exclude operational emails from communication limits. A couple notable exceptions:

 

  • Any sales insight emails without the unsubscribe footer and alerts, or those sent through the Sales Insight email plug-ins for Outlook or Gmail.
  • Marketo Mobile Engagement push notifications are not counted in communications limits, and you are not able to apply these limits to push notifications.

 

  1. What’s the best way to make sure leads who’ve reached their communication limits get the email later? As mentioned above, you can override the communication limits for this one email program or campaign. But if you want to respect your communication limits, I found some great tips on the community for this, such as:

 

  • The absolute best way to ensure leads who've reached their communication limits get an email later is to send emails through an engagement program. If leads reach their communication limits, they’ll simply receive the email in the next cast.
  • If you aren’t using an engagement program, do the manual thing: run a smart list for “not was sent email” and resend after the fact. Some of these leads could have been blocked for other reasons of course.
  • Or similarly, automate this process in your emails by including in your campaign after the “send email” flow: “remove from flow” if “was sent email," “wait X hours/days,” then “send email” again.

Thanks to Kristen Carmean, Cecily Gardner, andKenneth Elkington for their contributions to this post.

 

Did I miss any other scenarios? Let me know in the comments, and I’ll update this post.

Good old SOAP API. The SOAP API for custom objects has been around a while and its still a perfectly viable option for getting custom object data into Marketo. A note, I use SOAP UI as my tool of choice but of course you can use whatever you like. My screenshots will be generated there. (Note: You can read about using the REST API in Part 2 of the series)

 

The API calls you'll use are as follows

 

Most often you'll use the first two. Note that you'll supply the Link field and the dedupe fields to fully specify the object. Keep in mind, most often custom objects are intended to model data that exists in a one to many relationship with a Lead or Company. You can also send in multiple objects with each call, and this is the best practice. I have created integration which send up to 500 per call without issues.

 

Request

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:mkt="http://www.marketo.com/mktows/">

   <soapenv:Header>

      <mkt:AuthenticationHeader>

         <mktowsUserId>${#TestCase#userid}</mktowsUserId>

         <requestSignature>${#TestCase#signature}</requestSignature>

         <requestTimestamp>${#TestCase#timestamp}</requestTimestamp>

      </mkt:AuthenticationHeader>

   </soapenv:Header>

   <soapenv:Body>

      <mkt:paramsSyncCustomObjects>

         <objTypeName>automobile_c</objTypeName>

         <customObjList>

            <customObj>

               <customObjKeyList>

                  <attribute>

                     <attrName>emailaddress</attrName>

                     <attrValue>JMattos@Marketo.com</attrValue>

                  </attribute>

                  <attribute>

                     <attrName>vinnumber</attrName>

                     <attrValue>5NPDH4AE2DH181717</attrValue>

                  </attribute>

               </customObjKeyList>

               <customObjAttributeList>

                  <attribute>

                     <attrName>color</attrName>

                     <attrValue>Silver</attrValue>

                  </attribute>

                  <attribute>

                     <attrName>model</attrName>

                     <attrValue>Sonata</attrValue>

                  </attribute>

                  <attribute>

                     <attrName>make</attrName>

                     <attrValue>Hyundai</attrValue>

                  </attribute>

                  <attribute>

                     <attrName>yeah</attrName>

                     <attrValue>2015</attrValue>

                  </attribute>

               </customObjAttributeList>

            </customObj>

         </customObjList>

         <operation>UPSERT</operation>

      </mkt:paramsSyncCustomObjects>

   </soapenv:Body>

</soapenv:Envelope>

 

Response

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns1="http://www.marketo.com/mktows/">

   <SOAP-ENV:Body>

      <ns1:successSyncCustomObjects>

         <result>

            <syncCustomObjStatusList>

               <syncCustomObjStatus>

                  <objTypeName>automobile_c</objTypeName>

                  <customObjKeyList>

                     <attribute>

                        <attrName>emailaddress</attrName>

                        <attrType xsi:nil="true"/>

                        <attrValue>LJankins@Blizzard.com</attrValue>

                     </attribute>

                     <attribute>

                        <attrName>vinnumber</attrName>

                        <attrType xsi:nil="true"/>

                        <attrValue>5NPDH4AE2DH181717</attrValue>

                     </attribute>

                  </customObjKeyList>

                  <status>UPDATED</status>

               </syncCustomObjStatus>

            </syncCustomObjStatusList>

         </result>

      </ns1:successSyncCustomObjects>

   </SOAP-ENV:Body>

</SOAP-ENV:Envelope>

Next up, the REST API, which is, relatively speaking, a new thing. The custom object parts of the REST API are documented on the developer blog on their own separate page, and in my opinion it makes sense to monitor that page for changes so you know when the API has new features added.

 

For the purposes of this, I'll be referencing the Automobile object that I created in part 1 of this series, and I'll be using Postman to make my REST calls. (note you can read about use of the SOAP api in Part III of the series) Here's what it looks like:

 

Screen Shot 2015-07-07 at 6.16.40 PM.png

 

Create/Update Custom Objects

Request

http://491-XYZ-299.mktorest.com/rest/v1/customobjects/automobile_c.json?access_token=3471-4804-afd9-e9925fd632f9:sj

 

jSON Payload

{

  "action": "createOrUpdate",

  "dedupeBy": "dedupeFields",

  "input": [

    {

      "bodystyle": "Coupe",

      "color": "Silver",

      "make": "Hyundai",

      "model": "Sonata Hybrid",

      "year": "2015",

      "vinnumber": "KMHEC4A4XFA129411",

      "emailaddress": "jmattos@marketo.com"

    }

  ]

}

 

Response

{

  "requestId": "8ca7#14e6ad1cc70",

  "result": [

    {

      "seq": 0,

      "status": "created",

      "marketoGUID": "98f652e8-e8f0-47b1-a1f7-18dc005007c3"

    }

  ],

  "success": true

}

 

Delete Custom Objects

Request

http://491-XYZ-299.mktorest.com/rest/v1/customobjects/automobile_c/delete.json??access_token=3471-4804-afd9-e9925fd632f9:sj

 

jSON Payload

{

   "deleteBy":"dedupeFields",

   "input":[

      {

        "emailaddress":"jmattos@marketo.com",

        "vinnumber":"KMHEC4A4XFA129411"

      }

   ]

}

 

Response

{

  "requestId": "ed07#14e6b34c01e",

  "result": [

    {

      "seq": 0,

      "status": "deleted",

      "marketoGUID": "6c485902-3663-4b0b-adfd-e183e33cb285"

    }

  ],

  "success": true

}

 

So there you have it. a Sample REST call to Create a custom object, and one to Delete a custom object. The other calls are really quite similar.

"Marketo only" custom objects have been available for a while within Marketo, but up until recently you needed involvement from Support or Consulting to create them. Well, all that is changing in a recent enhancement to Marketo. If you need to leverage Custom Objects, you can request access via support, and this new end user facing UI is all yours. Amazing, Right?

 

Screen Shot 2015-06-19 at 3.56.29 PM.png

Once enabled, you'll see the Custom Objects under Admin --> Custom Objects

 

Lets talk a bit about why you might need or want to use custom objects. Custom objects are used to extend the Marketo data model and specify data that exists in a one to many relationship with a Lead or Company. Example of this might be "Products" or "Contracts" or "Investment Portfolios".. the possibilities are endless.

 

These objects, one created and published are populated using the SOAP or REST API and can be used in Smart Campaigns or Smart lists, and are viewable in the Lead Details screen under "Custom Objects"

 

The available Triggers and Filters for an object called "Literature" would be

Trigger

     Added to Literature - A Literature Object was added to a lead

Filters

     Was Added to Literature

     Has Literature

     Was Not Added to Literature

 

and as you can see.. the attributes of the Custom Object become constraints on the Filters and Trigger.

 

Screen Shot 2015-06-19 at 4.30.45 PM.png

Another cool way you can use custom objects is within Email Scripts! You can, for example, create a dynamic script token for an email that when the email is sent, shows all the values for a custom object in the system. You might use this to list out a set of stocks owned by a person, or a list of historical purchases. That will be discussed further in the Email Script sequel to this post.

 

Creating Custom Objects

Now that you know what they are and how to use them... how do you create them? Excellent question, and it's not hard. Firstly you need to design your object.

 

Custom objects, when created, are given 3 fields by default: Created At, Updated At, and Marketo GUID. The first two are obvious, but the Marketo GUID can serve as a unique identifier for the custom object.

Screen Shot 2015-06-19 at 4.43.29 PM.png

 

In addition to these fields you MUST create the following fields

 

  • a "Link" field - This field is the field that connects an object to the appropriate Marketo Lead or Company. you can choose Email Address, Marketo ID, or any custom field (Perhaps your company uses a unique "integration ID" for leads?). Please note. Be careful when creating the link field. This field, when you add data, MUST be a field that exists on the Lead or Company, and obviously must have a value on the Lead or Company that matches what you're upserting. Also, Ensure that the NAME and API NAME on the custom object match the API NAME on the Lead or Company. Trust me on this.

Screen Shot 2015-06-19 at 4.44.56 PM.png

  • a "Dedupe" field - This is another unique identifier that you can use to UPDATE existing custom objects once they're in Marketo. For example....if you're building a custom object called "Automobile" the Dedupe Field might be "VIN Number", which uniquely identifies the Automobile. When you go to update these objects, this is the field you use to identify the custom object, along with its associated Lead (Change the automobile with Vin=12345678 to now have a Color of "Green"). You can have one or more of these, as described in the special note below.

Screen Shot 2015-06-19 at 4.53.22 PM.png

Optionally, you can add other fields (Color, Make, Model, would be good candidates for an Automobile, so I'll add those, as shown.Screen Shot 2015-06-19 at 4.53.49 PM.pngHere's an important note. There are times youll have dedupe fields that are TRULY unique across your Marketo instance, things like Social Security Number or VIN Number.. you're sure no two people will own the same Car with the same VIN Number at the same time.Sometimes, however, you have dedupe fields that are NOT unique. Think about the example of a Product ID. A product like a smart phone might be assigned a product ID of ABC123. In that case, John and Mary might both own this product. In that case, youll have ProductID as a dedupe field, Email address as a link field AND a dedupe field! It will then the the COMBINATION of email and ProductID that constitute a unique custom object of type Product.Looking good! You might be wondering.. is the object live yet? No, not yet.. so lets talk state. The state of a Custom Object can be discussed for two aspects, the state of the object itself, and the state of a field on the object.Possible states are:

  • Object: Draft, Published, Published with Draft
  • Attribute: New, Deleted

 

Right now, all of our fields are "new" and the object itself is "Draft". To publish it so it's available for use, just click the publish button and see that these statuses change. Up until you publish the object you can change things about the object like the key fields etc.. but once its published, those key fields are locked down.. including the Link and Dedupe fields.

 

Screen Shot 2015-06-19 at 4.57.00 PM.png

Screen Shot 2015-06-19 at 4.58.15 PM.png

 

Once you're object is published, you can use it, and load it up with data using the REST or SOAP APIs (see  next week's blog on that)... or even BULK LOAD data. You read that right. Hop over to the Lead Database and you'll see New --> Import Custom Object Data. This option works a lot like importing leads. You can import a CSV and map the fields into your object. Obviously you'll have to include the link field, the dedupe fields and the data fields. You're limited to ~100mb per file.. and you can expect very high speed imports (up to 1,000,000 per hour)

 

Changing an Existing Object

Previously, this was awful and involved deleting the object data, dropping the object and recreating the object. No more! You're free to remove columns, add columns, and then republish the object! Click "new" to add a new field, and right click a deletable field and click "delete" to see those other two attribute states.

 

Screen Shot 2015-06-19 at 5.02.21 PM.png

 

As before.. NOTHING changes from an API or application perspective until you push the publish button.. then the changes are live.

 

Next up.. Custom Objects in Marketo - Part 2 - REST API !!!

Some of you may have seen the release notes have some new improvements for our integration with Microsoft Dynamics. In fact, there's actually more than are listed! So what do they mean for your integration?

 

  • Setup Validation Tool: This primarily will impact people who are setting up their integration for the first time. Some of you may remember these really ugly red script errors that would pop up over the dialog boxes when you had an error with your password or something else during the setup process. They were a little hard to read and kind of confusing. This new tool will go through and check some of the major mistakes we see made in the initial sync process and give you advice on what to do. I'm not going to spend too much more time typing about that because our Docs team actually already wrote up instructions on using it here.
  • Sync to Dynamics Flow Step Now in Real Time: Some may know that the Sync to Dynamics flow step actually just queues a lead to sync along with any other changes that have been made. Our Salesforce sync flow step actually runs in real time, so it jumps the new lead to the front of the line, essentially. If you have a lot of updates happening in your Dynamics instance today, you can find that brand new leads aren't making it over as quickly as you might like. This change should help you get those new leads over to CRM more quickly.
  • Add New Fields to Custom Entities: Right now, if you have a custom entity synced from Dynamics over to Marketo, you can't add new fields into the sync for that custom entity without disabling the sync. Unfortunately, disabling the sync requires you to remove every reference to the custom entity, which is not really very practical if you're actually using it (which in theory is why you synced it). So now, you will be able to add new fields to the entity without having to disable the sync and take all the references out from live or archived campaigns.
  • Performance Enhancements: There are a number of enhancements targeted at improving the sync performance. Not all of them are particularly interesting to blog about, but two worth mentioning are the use of a batch update API and the release of an asynchronous version of the plugin. Who doesn't like faster sync performance?
  • Create Contact Flow Action: This is coming out as a beta feature first, but now, instead of creating leads in CRM, you have the option to create contacts instead. I believe you'll then have to manage the account creation/association directly in CRM, but this is a huge product enhancement for the many Dynamics customers that are not using leads at all. This is "either or" situation, where you have to decide if your instance syncs only contacts or syncs only leads and once you select this option, you can't go back.

 

I'm super excited to see such a big batch of Dynamics changes in this release, and even more so because there's a bunch more to follow in the 2016 releases as well.

I've blogged before about Custom Activities, and at length about Custom Objects, but I'm often asked when to use these. Are they interchangeable? Why do we have both? Where am I?

 

So many questions. At a high level, and this may seem obvious but it helps to bear it in mind. Think of Custom objects as Nouns, and think of Custom Activities as Verbs. When you think of it like that, the difference is obvious, and the use cases write themselves.

 

Examples of Custom Objects

     Product

     Automobile

     Asset

     Portfolio

     Farm Animal

     Trailer

 

Examples of Custom Activities

     Subscribed to mobile app

     Purchased Product

     Leased an Automobile

     Deleted a Portfolio

 

Here's a comparison...

 

Custom ObjectCustom Activity
Can be created by you as a Marketo AdminMust be created by Support or Consulting
Can have individual instances added via the SOAP APICANNOT have individual instances added via the SOAP API
Can have individual instances added via the REST APICan have individual instances added via the REST API
Can be used in Email ScriptsCANNOT be used in Email scripts
Can trigger off the insertion of Custom ObjectsCan trigger off the addition of Custom Activities
Can filter on "has Custom Object"Can Filter on "has Custom Activity"
Can update and deleteCannot programmatically delete or update

 

As you can see below comparing the available Triggers and Filters for a Custom Object and a Custom Activity, in a Custom Activity there is no concept of "has custom activity" because they are by their nature, in the activity log of the associated lead, whereas the Custom Object very much exists in a current state "this lead owns these Apple products" vs "this lead made Purchases"

Screen Shot 2015-10-06 at 12.57.34 PM.png

 

Screenshot 1: Available Filters and Triggers for a Custom Object

 

Add Milestone.png

Screenshot 2: Available Filters and Triggers for a Custom Activity

 

 

 

So you can see, they really each have their place. What are your use cases? Add a commend below and tell us!

Having been in Marketo Enterprise consulting for about 2 years I've seen a fair few cool Webhook solutions.. here are a few of my favorites that may give you some inspiration

 

1. Calling a service that generates a unique software download URL

     One of our clients wanted to generate a UNIQUE URL for a software download when a Lead filled out a form (and as a bonus, they became known marketable leads when they requested it). A third party takes in a unique super secret ID and generates that unique URL.

 

As you can see below, the jSON coming back is mapped into an attribute on the lead. We can then trigger a campaign to the user and send them their trial.

skitch.png

skitch-1.png

 

2. Sending SMS messages with Twilio

     This one was one of mine, and I documented it right here on the Marketo Whisperer blog recently (Sending an SMS using Twilio)

 

3. Sending push notifications with Urban Airship from a mobile app (before there was Marketo Mobile Engagement)

     Before there was Marketo Mobile Engagement, which you should absolutely check out immediately, there were other providers of simple Server Side Push messaging such as Urban Airship.

 

     This one is really powerful because it also leverages other parts of Marketo like Custom Activities. You can imagine how cool it is to sign up for a mobile app and receive push notifications along with other marketing content. We can send reminders, contact other people and even do deep linking back into the Mobile app.

 

     Here you'll notice that we get back some interesting tracking information from UA, which we could then report on using the UA Reporting API.

skitch-3.png

 

 

After building a revenue model in Marketo and letting it run for a few months, you will want to make sure it is working properly so that you can get the reporting that you want. Here are five fairly straightforward, if sometimes time-consuming, things you can do to validate your lifecycle.

  1. Create a segmentation to track which records are in which segments. Each segment should contain one revenue stage with the filter Revenue Stage. Any record that's in the Default segment is most likely misplaced (unless it belongs to an exclusion list). You can then use smart lists to further dig down into the Default segment and figure out why people aren't in the lifecycle when they should be. You can also use the segmentations to get a quick count of people in each stage and dig into any stages where you are seeing much higher or lower numbers than expected. (Yes, technically you can do all of this with a bunch of smart lists if you don't want to waste a segmentation temporarily on this, but I think the segmentation is nice because you can see everything all at once.)

  2. Check that your Lifecycle Status field matches the Revenue Stage that a lead is in. I do this with smart lists, once for each stage, to find people in a particular stage that have a different Lifecycle Status value. Any time I see a mismatch, I know there's a problem that I need to dig into.
  3. Look at a Lead Flow report in RCE. Use the Model Performance Analysis (Leads) report with Rows Stage and To Stage, Column Month, and Measure Flow. You want to be watching for any leads that seem to be moving backwards in the lifecycle instead of forward, which is a common problem with poorly built models. For example, if Known is your first stage, then you would expect to see leads moving from Known to any stage forward. If you see leads moving from MQL to Known, then your model must be adjusted.
  4. Look at the results log of each smart campaign that moves leads around in the lifecycle. Look for counts that are much higher or lower than expected (e.g. Really, we had 1000 leads go through the MQL campaign this month but we only had 50 leads actually become MQL?) Skim for things that look out of order, particularly Skipped Do Nothing messages and anything where you see a Revenue Stage Change that you do not expect. View the activity logs of some sample records to see if there’s anything unusual happening that might be causing those messages.

  5. Pick one stage and check the people in that smart campaign or stage against select criteria in a separate smart list. (You can also do this with a particular date if you prefer. For example, just randomly select September 18 and go and look at each lead that moved in or out of any stage on that date to validate. This is my version of spot-checking the lifecycle.) For example, you might look at all the MQLs to ensure that they have actually hit your score threshold or all of the people in Lost to see if any of them have open or won opportunities associated to them. You can also do the reverse - look for people with lost opportunities who are not in the Lost stage.