Category: How To

  • Building a Scalable Alert System in Marketo

    Building a Scalable Alert System in Marketo

    “What have you done for me today?”
    It’s the unspoken question asked every day by sales teams. Alignment between sales and marketing teams has a lot to do with communication and visibility. If sales doesn’t see the value of marketing at a daily, tactical level, trust erodes fast.

    There’s entire books sales and marketing alignment. I’m not here to write one of those. Instead, I’ll show how redesigning a simple but critical process, your lead alerts, can up your perceived value to your sales team.

    When I first started using Marketo, my sales team was in a constant state of flux. There were new and departing faces, and management would completely redefine territories at the first sign of a stalled pipeline. As the designated Marketo jockey, it was up to me to ensure the right reps saw the right notifications. But keeping this up to date in Marketo was both time consuming and tricky to keep accurate everywhere.

    Sound familiar?

    If you’ve just adopted marketing automation, you’ll have handful of situations where you’d want to send an alert, such as the contact-us form on the website. This is easy to do—just create a smart campaign that triggers off a specific form fill, and runs a flow step of send alert to lead owner.

    Simple Alerts
    An example of the simplest of lead alerts. They’re easy to build, but you’ll outgrow them quickly.

    But as you grow, you’ll add more forms and different alerts for different offers. You’ll also need to keep pace with a growing and evolving sales organization. Soon your simple alert processes will get unwieldy (and unreliable).

    If you’re at this point, the first step you should take is in adopting some global assets, particularly with your forms (See #4 in this post for more on that topic).

    Think about the forms you can use within multiple programs. For example, a “download a whitepaper” form could be the same form re-used for different whitepapers. If you can’t do that, at least create a common naming convention e.g. “Form – Contact Us”, “Form – Contact Us v2” etc. This is handy because your alerts can start to live in one place, and you can trigger off of all-inclusive logic like “form name contains “Contact Us”.

    Form name contains example
    Name your forms consistently, and you can rely on much more open filter logic

    You’ll find this will close some of the gaps in your alerts, and will help wrangle the odd campaign sending out alerts when it shouldn’t be.  This is an elegant solution, as long as you keep your naming conventions tight.

    But then comes the process of determining who should get which alerts. If you’re like me, your sales team is carved up by geographic region. If you’re syncing your leads to salesforce, and they’re then getting assigned to the reps, you can just use the lead owner info to determine who should get which alert. But what if the audience you want to alert doesn’t own records in SFDC? This often happens with account management teams, SDR teams, or organizations using lead queues (If you haven’t discovered it yet, lead queues make the {{lead.lead owner}} tokens unusable). For situations where you can’t lean on CRM data, you need to adapt Marketo to handle this.

    When you’re at scale with a complex territory assignment rules that change often, and more than a handful alerts to manage, you can build your alerts based on Segmentations and Program Tokens ({{my.Tokens}}). These will let you update territories and recipients in one place, with changes immediately affecting all your alerts.

    Using a Segmentation to define sales territories

    Marketo Segmentation for Geography
    Now you’ve got a reliable way to identify which territory a given lead belongs to.

    First create a new Segmentation, and define your segments based on your sales team’s territory assignments. In the filters of each segment, you’d use country or whatever field that defines geography to specify that segment. Once approved, Marketo will slice up your data and dump leads into the appropriate buckets.

    If you haven’t already, it’s time to create a central program for all your alerts. Build out your first smart campaign with the appropriate trigger, eg: Form name starts with “Contact Us”. For the flow step, you’ll send an alert with a conditional statement for each of the segments you defined earlier.

    This tells Marketo to send a particular alert to a particular person based on which segment the lead (which triggered the alert campaign) is a member of.

    Using a marketo segmentation as conditional logic
    You can use the segmentation you just created as filter criteria, or, in this case, conditional logic for your alerts.

    Note: While we’re using this segmentation for a somewhat unusual purpose, it’s also great for dynamic content (for which it was originally designed for). Most people under use Segmentations, but it’s a great feature with some pretty cool use cases far beyond this example.

    Using tokens to define alert recipients

    Now we’ve got our logic in place, but what we’re most concerned about is who the alert is going to. You could plug in a list of email addresses under the “to other recipients” section. But remember that anytime your assignments change or you hire a new rep, you’ve got to change that in every alert campaign. It’ll seem easy now, but it’ll be a pain later. Trust me.

    So instead, go into the My tokens area of your program, and create text tokens with consistent names like {{my.NW-Sales-Rep}}. Do this for for each of your territories and reps, and set the token values to their email addresses.

    Setting Marketo tokens for alerts
    Create tokens for each of your regions. Note: It’s possible to put several emails in a single token value. Just separate them with a comma.

    Once your tokens are all set, plug them into the flow step choices under “other recipients”. Marketo will send to the token values whenever the alert fires.

    Setting tokens in Marketo flowsteps
    Your alert flowstep will now be a long set of choice steps, each with a different segment and corresponding token.

    Note: You can only use tokens in a smart campaign like this when it’s based on at trigger. You cannot use {{my.Tokens}} in batch smart campaigns.

    Bringing it all together

    Once you’ve built out the rest of your alerts and set all your tokens, you’ll feel like you did a lot of work for no clear reason.

    But you’ll see this pay off when your territories and sales teams start to change. You’ll find that you can skip edits to individual alerts, and instead update either tokens or Segmentations, depending on what’s changing.

    You’ll save time, but most importantly, you’ll ensure consistency and reliability for the alerts to your sales teams.

  • Updated: Tracking Embedded YouTube and Wistia Videos in Marketo

    Updated: Tracking Embedded YouTube and Wistia Videos in Marketo

    Update 5/26 – I’ve fixed a player dimensions issue with the Wistia embed script, and added the ability to track both video starts and video completions. I’ve also updated the token naming conventions with a clearer, more consistent naming convention. Finally I removed the munchkin script call at the top of each embed code (though enabling Munchkin API is still necessary). It’s not necessary if you already have munchkin installed on your pages. Let me know if these changes are helpful!

    A common need among Marketo users lies in the ability to track embedded video engagement with their prospects and customers. Marketo will natively track form submissions and web page activity, but it does not have great built-in video tracking functionality.

    Since it’s important for marketers to understand when their target audiences actually view or interact in a certain way with a video, and not just that they visited a web page that happened to have a video on it, a more robust solution is needed. There are vendors who specialize in tracking video behavior in your marketing automation, but for basic tracking, you can do it yourself, and I’ll show you how.

    By leveraging Marketo’s munchkin API in conjunction with an API-enabled video hosting service like YouTube or Wistia, it’s easy to build this integration yourself. Before we get any further: don’t get scared off by terms like “API”–this particular piece of functionality is actually pretty simple to implement with a basic understanding of HTML and Marketo, and I’ve hopefully done most of the heavy lifting for you. Plus, it’s a great practical demonstration of the extensibility of the Marketo platform.

    This implementation works by using the video player to tell Marketo when it’s state changes from not playing to playing (in other words, when the lead clicks the play button on an embedded video). Then Marketo logs a web page visit event in the lead’s activity log, which can be used to trigger other actions off of Marketo, such as an interesting moment or program status change.

    First Things First: Enable Munchkin API

    Before we get into the specifics of how this works, you’ll first need to set up your Marketo instance to use the Munchkin API. Marketo Admins should first navigate to their admin section > Integration > Munchkin > Edit API Configuration. You’ll want to check the box labeled “Enable Munchkin API”

    Enable Munchkin APIWhile you’re on your Munchkin Settings, also make note of your nine-digit Munchkin ID (formatted as XXX-XXX-XXX). You’ll need this later.

    Now that you have this squared away, you’re set to start setting up your customized embed code. I’ve set up codes for both YouTube and Wistia. While YouTube is certainly a more widely used platform, I’ve started using Wistia more recently because of the issues with corporate IT filters blocking YouTube videos for B2B users. While this isn’t always an issue for embedded videos, I ended up preferring the the customization and business focus of Wistia. It’s a matter of personal preference I’ll leave up to you. For each guide, I’ve included standard embed codes, and tokenized codes (if you’re using your Marketo Programs).

    Option 1: Embedding with My.Tokens

    I mentioned that there are two versions of these embed codes – a standard and a token enabled script. If possible, you really should use the token-enabled script. You’ll find it’s far easier to work with, so long as the page you want to embed your video on is contained within a Marketo Program.

    First are the modified versions of the embed codes for Wistia and YouTube that are set to accept Marketo’s My Tokens, which work within Programs. Also make special note the highlighted section for Munchkin ID. You will want to set this manually, since it’s the same value for your entire Marketo instance. Your tracking will not work without setting this up.

    To set up video play tracking for a Wistia or YouTube video, you’ll need a few things:

    1. Your video ID (10 digit code that you can find in the embed code on Wistia, or on the video URL – The same is true for YouTube, but the code is 9 digits)
    2. Video height and width dimensions (eg 550×309)
    3. A “play” URL that you want Marketo to log anytime the video is played
    4. Your 9-digit Munchkin ID

    Next, you’ll need a landing page to embed your video to. Generally it’s advisable to do this within a program so that you can make use of the token-enabled script, however if you’re comfortable editing the script yourself and cannot make use of program tokens, you can install the videos on really any landing page using the standard scripts at the end of this post.

    If you plan to use the token-enabled script, here are the tokens you’ll need to create (all should be plain text tokens):

    • My.Video – ID: the 10 digit video ID from wistia  (9 digit for YouTube)
    • My.Video – Width: The pixel width of the video (note: this should be input as a numerical value only, eg: “550”, and not “550px”.)
    • My.Video – Height: the pixel height of the video (same instructions as my.videowidth)
    • My.Video – Name No Spaces: this is the fictitious URL you define that will display in the Marketo activity log. You can set anything you want here, but I generally like to follow a similar naming convention to the page that the video is embedded on. I’ll clarify with an example: if your video is embedded on info.yourdomain.com/myvideo.html,  you might want the log to display info.yourdomain.com/myvideo/play when the video is played. In that case, you’ll want to set this token value as “myvideo”. Do not include any other part of the URL – Marketo will do that automatically. Note that this script logs a video start and a video complete event. You can opt to use one or the other, or both at the same time.
    • My.Video – Player Color: This one is optional, and only for Wistia, but it controls the color of the video player. You don’t need to set a value here, but if you want to customize it to your own video branding, feel free to use your own hexadecimal color code. (eg 6688AAD – no # needed)

    Below are the scripts you’ll want to place within an HTML object on a Marketo landing page. Note: The codes below will replace any embed code you would ordinarily retrieve from Wistia or YouTube directly. These will handle both the embed of the video and the tracking and integration within Marketo.

    Remember – you must update the highlighted sections with your specific Marketo 9-digit Marketo ID (including hyphens).

    You can also download all the scripts via my GitHub repository of this project.

     Wistia (With Tokens)

    <!--Video embed (this is what embeds the Wistia player)-->
    <div id="wistia_{{my.Video - ID:default=c6xf9ao18h}}" class="wistia_embed" style="width:{{my.Video - Width:default=550}}px;height:{{my.Video - Height:default=309}}px;" data-video-width="{{my.Video - Width:default=550}}" data-video-height="{{my.Video - Height:default=309}}"></div>
    <script charset="ISO-8859-1" src="//fast.wistia.com/assets/external/E-v1.js"></script>
    <script>
     wistiaEmbed = Wistia.embed("{{my.Video - ID:default=c6xf9ao18h}}", {
     videoWidth: {{my.Video - Width:default=550}},
     videoHeight: {{my.Video - Height:default=309}},
     playerColor: "{{my.Video - Player Color:default=688AAD}}"
     });
     // the functions below will watch for the video to be started or ended (tracked via state changes), and translating that to page visits in Marketo. 
     wistiaEmbed.bind('play', function() {
     mktoMunchkin("XXX-XXX-XXX");
     mktoMunchkinFunction('visitWebPage', {
     url: '/{{my.Video - Name No Spaces}}/played', params: 'x=y&2=3'
     });
     });
     wistiaEmbed.bind('end', function() {
     mktoMunchkin("XXX-XXX-XXX");
     mktoMunchkinFunction('visitWebPage', {
     url: '/{{my.Video - Name No Spaces}}/completed', params: 'x=y&2=3'
     });
     });
    </script>

    YouTube (With Tokens)

    <!--Youtube iframe embed script with Munchkin integration-->
    <div id="player"></div>
     <script>
     // 2. This code loads the IFrame Player API code asynchronously.
     var tag = document.createElement('script');
     tag.src = "https://www.youtube.com/iframe_api";
     var firstScriptTag = document.getElementsByTagName('script')[0];
     firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
     // 3. This function creates an <iframe> (and YouTube player)
     // after the API code downloads.
     var player;
     function onYouTubeIframeAPIReady() {
     player = new YT.Player('player', {
     height: '{{my.Video - Height:default=309}}',
     width: '{{my.Video - Width:default=550}}',
     videoId: '{{my.Video - ID:default=c6xf9ao18h}}',
     playerVars: { 'showinfo': 0, 'controls': 2, 'rel': 0 },
     events: {
     'onReady': onPlayerReady,
     'onStateChange': onPlayerStateChange
     }
     });}
     // 4. The API will call this function when the video player is ready.
     function onPlayerReady(event) {
     }
     // 5. The API calls this function when the player's state changes, and sends a visit web page action to Marketo via the Munchkin API
     var done = false;
     function onPlayerStateChange(event) {
     if (event.data == YT.PlayerState.PLAYING && !done) {
     mktoMunchkin("XXX-XXX-XXX");
     mktoMunchkinFunction('visitWebPage', {
     url: '/{{my.Video - Name No Spaces}}/started', params: 'x=y&2=3'
     });
     }
     else if (event.data == YT.PlayerState.ENDED && !done) {
     mktoMunchkin("XXX-XXX-XXX");
     mktoMunchkinFunction('visitWebPage', {
     url: '/{{my.Video - Name No Spaces}}/completed', params: 'x=y&2=3'
     });
     }
     }
     </script>
    
    

    Standard Embed Codes

    If for some reason you can't use your video within a Marketo program and use the tokenized codes above, the standard codes below will also work, just know that you must edit the highlighted portions with your video and Marketo info. Take extra care with the Wistia embed code, as variables like video player dimensions and ID must be edited in several places. Again, use the tokenized version above if you can! Finally, note the highlighted portion for “url”. Remember, this is the name of the URL you wish to have logged in a lead’s Marketo activity log when the video is played. This can be set to anything, and doesn't need to be an actual working URL. In the example of a webinar, your URL could be “myQ2Webinar/play”. Note to only include the page name and then something afterwards to distinguish the actual page from the play action, such as  "/play". Do not include any prefixes or domains (http, www, domainname.com, etc).

    Wistia (Standard Script, no Tokens)

    <!--Video embed (this is what embeds the Wistia player)-->
    <div id="wistia_29b0fbf547" class="wistia_embed" style="width:550px;height:309px;" data-video-width="550" data-video-height="309"></div>
    <script charset="ISO-8859-1" src="//fast.wistia.com/assets/external/E-v1.js"></script>
    <script>
    wistiaEmbed = Wistia.embed("29b0fbf547", {
     videoWidth: 550,
     videoHeight: 309,
     playerColor: "688AAD"
    });
     // the functions below will watch for the video to be started or ended (tracked via state changes), and translating that to page visits in Marketo.
    wistiaEmbed.bind('play', function() {
     mktoMunchkin("XXX-XXX-XXX");
     mktoMunchkinFunction('visitWebPage', {
     url: '/YourVideoName/started', params: 'x=y&2=3'
    });
    });
     wistiaEmbed.bind('end', function() {
     mktoMunchkin("XXX-XXX-XXX");
     mktoMunchkinFunction('visitWebPage', {
     url: '/YourVideoName/completed', params: 'x=y&2=3'
     });
     });
    </script>

    YouTube (Without Tokens)

    <!--Youtube iframe embed script with Munchkin integration-->
    <div id="player"></div>
     <script>
     // 2. This code loads the IFrame Player API code asynchronously.
     var tag = document.createElement('script');
     tag.src = "https://www.youtube.com/iframe_api";
     var firstScriptTag = document.getElementsByTagName('script')[0];
     firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
     // 3. This function creates an <iframe> (and YouTube player)
     // after the API code downloads.
     var player;
     function onYouTubeIframeAPIReady() {
     player = new YT.Player('player', {
     height: '390',
     width: '640',
     videoId: 'kTcRRaXV-fg',
     layerVars: { 'showinfo': 0, 'controls': 2, 'rel': 0 },
     events: {
     'onReady': onPlayerReady,
     'onStateChange': onPlayerStateChange
     }
     });}
     // 4. The API will call this function when the video player is ready.
     function onPlayerReady(event) {
     }
     // 5. The API calls this function when the player's state changes, and sends a visit web page action to Marketo via the Munchkin API. Make sure to update the mktoMunchkin value to match your specific account ID (Admin > Integration > Munchkin)
     var done = false;
     function onPlayerStateChange(event) {
     if (event.data == YT.PlayerState.PLAYING && !done) {
     mktoMunchkin("XXX-XXX-XXX");
     mktoMunchkinFunction('visitWebPage', {
     url: '/YourVideoName/started', params: 'x=y&2=3'
     });
     }
     else if (event.data == YT.PlayerState.ENDED && !done) {
     mktoMunchkin("XXX-XXX-XXX");
     mktoMunchkinFunction('visitWebPage', {
     url: '/YourVideoName/completed', params: 'x=y&2=3'
     });
     }
     }
     </script>
    
    Once you've successfully embedded your codes, It's time to test out your page. Visit the Marketo landing page you've just created, and click the play button on your video. Make sure to be using a browser that has already been cookied by Marketo (An easy way to confirm this is to visit a Marketo page with a form on it - if the form is pre-filled with your information, you're cookied). Then, search for your lead record in the Marketo lead database, and click over to the activity log. You should see something like this: activity log This web page will now appear anytime the video you've set up is played. Cool, huh?

    Triggering flowsteps off video play behavior

    So what do you do now? Now that you've got your videos tracked in Marketo, it's time to have Marketo do something interesting with that information. Since you've logged a web page visit, you can now use the "visited web page" trigger or corresponding filter in a Marketo Smart Campaign to trigger activities off of video plays. web page trigger   For example, you could log an interesting moment anytime your video is played. Your sales team will thank you for this, as you can log something very explanatory, like "Viewed Video: Q2 Product Demo" instead of "visited web page my-landing-page-Q2_Demo-V8.html/play." In the past I've discussed how to centralize your content tracking through Marketo programs. You can do the same with videos too, and log a program success when a lead plays one of your videos. This is especially helpful if you want to view all the leads who've watched your video, or to calculate return on the investment of a video's production. Flowstep   Keep in mind that these examples work best when the lead is already known in your database. So in the case of a recorded webinar, where you've probably got a form sitting in front of that video, it's safe to assume that you'll probably have known visitors being tagged with video views. But if the video is a general marketing video that may be sitting on its own, you will likely have anonymous as well as known visitors. Marketo will still track both, but logging a program status change or interesting moment is really only of value to known leads. So you may consider dropping in a filter to your smart campaigns to exclude anonymous leads, or just be willing to accept some anonymos leads in your program reports.

    Moving beyond the basics

    I built this integration because it solved a very specific problem for me, yet there are pretty limitless possibilities with expanding on this. With a bit of work, it's likely possible to track more nuanced behavior, such as viewing a video for a specified period of time, or observing the degree to which the video is started and stopped. I constructed this integration using the following resources. Feel free to use these in your own efforts! Marketo Munchkin API Documentation Wistia Player API Documentation Youtube JS Player API Reference As I mentioned earlier, I've started with Wistia and YouTube, but there are probably plenty of other video players you could build similar integrations with, such as Vimeo. Most of their APIs are fairly similar to work with, so it's probably just a matter of adapting the existing scripts to other players' specific operations. If you're interested in other applications of this, let me know in the comments!