Skip navigation
All Places > Products > Blog > 2017 > November
2017
Sanford Whiteman

Fixing Marketo pURLs

Posted by Sanford Whiteman Nov 30, 2017

It's well-known that Marketo's pURL feature, out-of-the-box, has a fatal (and kinda fascinating) shortcoming. If someone has visited your site before — meaning either an anonymous or associated Munchkin session— then pURL-enabled pages aren't functional.

When there's an existing anonymous session, the server ignores the personalized part of the URL (the Marketo Unique Name /JillSmith02 or Unique Code /XYZPDQ) and serves up default/empty content.

On the other hand, if the person has never been to your site on their current device, pURLs work fine.

Unfortunately, then, pURLs work only for people who either [a] just got a new PC or phone or [b] have been living under a relative rock. Not exactly the widest audience!

Luckily, it's always been possible to fix the strange session behavior with a little JavaScript.

 

 

Read the full post on TEKNKL :: Blog →

With an assist from Velocity, your emails can have time-responsive content.  (And I don't just mean Happy ${day_of_week}, ${first_name}!)

 

  • When the same email is resent with different primary content (e.g. a weekly newsletter), Velocity can customize secondary content based on the day: like reader PW, you can show a special promo only in the first send of the month, every month.
  • Like user GM, you can pre-create a series of different content blocks, in effect creating a drip campaign from just one asset.
  • If a triggered email is sent off-hours, you can notify the recipient that they'll hear from Sales on the next business day.
  • Or lots of other adventures!

 

To run the snippets below, set common variables at the top of the script token or in your global {{my.includes}} token (you do have one, right?) like so:

 

#set( $defaultTimeZone = $date.getTimeZone().getTimeZone("America/New_York") )
#set( $defaultLocale = $date.getLocale() )
#set( $calNow = $date.getCalendar() )
#set( $ret = $calNow.setTimeZone($defaultTimeZone) )
#set( $calConst = $field.in($calNow) )
#set( $ISO8601 = "yyyy-MM-dd'T'HH:mm:ss" )
#set( $ISO8601DateOnly = "yyyy-MM-dd" )

 

I cannot stress enough that setting the IANA time zone for your location is critical when using Date or Calendar objects in Velocity.  If you do not do this as is the case, unfortunately, with some old code snippets on Marketo's blog your code is broken. I won't rehash the reasons why here (happy to in the comments) but believe me you must set the timezone!

 

Now, for some examples...

 

Check the current day of the month

#set( $calNow = $date.getCalendar() )
#if( $calNow.get($calConst.DAY_OF_MONTH) <= 7 )
It's one of the first 7 days of the month!
#end

 

Check the current week

#if( $calNow.get($calConst.WEEK_OF_MONTH) == 1 )
It's the first calendar week of the month!
#end

 

#if( $calNow.get($calConst.WEEK_OF_MONTH) == $calNow.getActualMaximum($calConst.WEEK_OF_MONTH) )
It's the last week of the month!
#end

 

Check if it's the Nth Something-day of the month

#if( $calNow.get($calConst.DAY_OF_WEEK) == $calConst.WEDNESDAY &&
     $calNow.get($calConst.DAY_OF_WEEK_IN_MONTH) == 3 )
It's the 3rd Wednesday of the month!
#end

 

Is it during business hours?

#set( $calStartOfBusiness = $date.getCalendar() )
#set( $ret = $calStartOfBusiness.setTimeZone($defaultTimeZone) )
#set( $ret = $calStartOfBusiness.set(
   $calStartOfBusiness.get($calConst.YEAR),
   $calStartOfBusiness.get($calConst.MONTH),
   $calStartOfBusiness.get($calConst.DAY_OF_MONTH),
   8,
   0,
   0
) )
#set( $ret = $calStartOfBusiness.set($calConst.MILLISECOND,0) )
#set( $calCloseOfBusiness = $date.getCalendar() )
#set( $ret = $calCloseOfBusiness.setTimeZone($defaultTimeZone) )
#set( $ret = $calCloseOfBusiness.set(
   $calCloseOfBusiness.get($calConst.YEAR),
   $calCloseOfBusiness.get($calConst.MONTH),
   $calCloseOfBusiness.get($calConst.DAY_OF_MONTH),
   17,
   0,
   0
) )
#set( $ret = $calCloseOfBusiness.set($calConst.MILLISECOND,0) )
#if( $calNow.compareTo($calStartOfBusiness) >= 0 && $calNow.compareTo($calCloseOfBusiness) <= 0 )
It's during business hours!
#end

 

Note here that 8,0,0 and 17,0,0 are setting the hour, minute, and second respectively, in 24-hour time.

 

8,0,0 means 08:00:00 or 8 a.m. and 17,0,0 means 17:00:00 or 5 p.m.

 

Is it a business day?

#set( $businessDays = [
  $calConst.MONDAY,
  $calConst.TUESDAY,
  $calConst.WEDNESDAY,
  $calConst.THURSDAY,
  $calConst.FRIDAY
] )
#if( $businessDays.contains($calNow.get($calConst.DAY_OF_WEEK)) )
It's a work day!
#end

 

You can of course combine this business days check with business hours above.

 

Is our timed promo active?

#set( $calStartOfPromo = $convert.toCalendar(
  $convert.parseDate(
    "2017-11-15T00:00:00",
    $ISO8601,
    $defaultLocale,
    $defaultTimeZone
  )
) )
#set( $calEndOfPromo = $convert.toCalendar(
  $convert.parseDate(
    "2017-12-01T00:00:00",
    $ISO8601,
    $defaultLocale,
    $defaultTimeZone
  )
) )
#if( $calNow.compareTo($calStartOfPromo) >=0 && $calNow.before($calEndOfPromo) )
The promo is active!
#end

 

Note again the mandatory use of defaultTimeZone when initializing new Dates.

 

And check out how I'm using compareTo and before to see if we're currently greater than or equal to the start date and less than the end date.

 

You could substitute compareTo($calEndOfPromo) < 0 for before($calEndOfPromo) as it's the same logic, just a tiny bit longer.

 

Promo expires 7 days from today (whenever that is)

$calNow.add($calConst.DATE,7)
#set( $FRIENDLY_24H_DATETIME_WITH_FRIENDLY_TZ = "MMM dd, yyyy HH:mm z" )
Our promo expires 7 days from today, which is
${date.format(
  $FRIENDLY_24H_DATETIME_WITH_FRIENDLY_TZ,
  $calNow,
  $defaultLocale,
  $defaultTimeZone
)}

 

This quickie shows how to shift a certain number of days from today. To go backwards 7 days, use add($calConst.DATE,-7) (there's no explicit subtract method).

 

How long will the promo last?

#set( $ret = $calNow.set(
   $calNow.get($calConst.YEAR),
   $calNow.get($calConst.MONTH),
   $calNow.get($calConst.DAY_OF_MONTH),
   0,
   0,
   0
) )
#set( $ret = $calNow.set($calConst.MILLISECOND,0) )
#set( $calEndOfPromo = $convert.toCalendar(
  $convert.parseDate(
    "2018-01-22T00:00:00",
    $ISO8601,
    $defaultLocale,
    $defaultTimeZone
  )
) )
#set( $diffRemaining = $date.difference($calNow,$calEndOfPromo) )
#set( $daysRemaining = $convert.toInteger($diffRemaining.getDays()) )
#set( $weeksRemaining = $convert.toInteger($diffRemaining.getWeeks()) )
The promo
#if( $weeksRemaining > 0 )
ends in ${weeksRemaining} ${display.plural($weeksRemaining,"week","weeks")}!
#elseif( $daysRemaining > 0 )
ends in ${daysRemaining} ${display.plural($daysRemaining,"day","days")}!
#elseif( $daysRemaining == 0 )
ends today!
#else
already ended!
#end

 

Unlike adding and subtracting days to/from today, differencing dates is relatively complex.

 

First, you usually[1] want to align dates to midnight (yyyy-MM-ddT00:00:00.000) boundaries. That's why I set the hours, minutes, seconds, and milliseconds of $calNow all to zero, to create a Calendar object representing "Today at midnight."

 

Then the end date is also anchored at 00:00:00 (you could use any time of day, as long it's the same for start and end, but midnight is easiest).

 

Once aligned, you won't get any fractional-day surprises with $date.difference(). difference() returns a robust Comparison object, from which you get the count of days, weeks, and so on between the dates.

 

I also took this opportunity to use $display.plural(), which isn't a date-related feature but just another cool Velocity thing you should know. plural() works with Integers, though, while Comparison.get accessors return Longs. That's why $convert.toInteger() is in there.

 

Times like this, you can see why I say Velocity is anything but simple. So if you're really a newbie, you shouldn't say, "I'm not too advanced with Velocity" as if you're just a couple scripts away from mastery! To truly add Velocity to your skill stack is a slow grind.

 

Add an ordinal indicator to the day, like “1st” or “15th” instead of just “1” or “15”

#define( $enUSDayOrdinalIndicators )
1st 2nd 3rd 4th 5th 6th 7th 8th 9th 10th 11th 12th 13th 14th 15th 16th 17th 18th 19th 20th 21st 22nd 23rd 24th 25th 26th 27th 28th 29th 30th 31st
#end
#set( $indicatorList = $enUSDayOrdinalIndicators.toString().trim().split("\s?\d+") )
Today with a friendly ordinal indicator (is
${date.format(
  "EEEE, MMMM d'${indicatorList[$calNow.get($calConst.DAY_OF_MONTH)]}'",
  $calNow,
  $defaultLocale,
  $defaultTimeZone
)}

 

This add-on will give you a super-friendly date display, which isn't natively supported by Java or Velocity:

 

Wednesday, August 15th

 

(The "th" is the non-native part.)

 

It should be clear that this is very culturally-specific stuff, and since it isn't part of the localized parts of Java Calendar (which I mean to write a dedicated post on soon) you would have to add your own localized Nth and Nst for locales other than en-*, some of which never use indicators at all, like Swedish.

 

 

Learning More

Get confused enlightened by the Java Calendar docs.

 

 


 

Notes

[1] Exception is when a period ends at, say, exactly 5:00 p.m. on a certain date and you do want to take hours (fractional days) into account. Sweepstakes laws might require such precision. Or if you're trying to do something like hours-until-webinar, you'd also want to align to hours (still zero out minutes/seconds/millis for sanity).

Twilio offers a pretty awesome Lookup API to enrich phone numbers with metadata: it can distinguish mobile and landline numbers (Sales will thank you!), determine carrier (which has demographic significance, like it or not), and even do reverse Caller ID lookup.

It's reasonably priced, and if anyone knows this stuff, it's Twilio.

The weird thing is that even though the Lookup API is 100% webhook-compatible, their docs don't show it being called as a simple webhook request. They only show it in the context of Java, PHP, or other code.

Anyway, here's what's needed to call it as a webhook.

Lookup requests are authenticated using HTTP Basic Auth. Your Twilio Account SID is the username; your Account Token is the password.

    So you just need to create an HTTP Authorization header and then add it to the webhook definition in Marketo. (Marketo supports Basic Auth just fine, but it doesn't present you with distinct username and password boxes.)

    An Authorization header for Basic auth looks like

Authorization: Basic <base64(<username>:<password>)>

where <base64(<username>:<password>)> means simply

  • concatenate the username and the password with a colon : in-between
  • Base64-encode the concatenated string

 

 

Read the full post on TEKNKL :: Blog →

Here’s what I learned on Day One at Marketo: even after more than two decades in Marketing, Sales, and GM roles having worked in the C-suite at multiple companies and counseled a number of global chief executives, nothing could have prepared me for becoming a CEO for the first time.

 

It used to be that a new CEO had a grace period. In your first weeks and months on the job, you were expected to embark on a listening tour, taking time to get to know your team, products, and customers. You would make incremental changes at the outset – just enough to hint at your leadership style, but not so big as to make waves.

 

That luxury no longer exists. Technology is disrupting and reshaping the marketing industry every day. The landscape is incredibly unsettled. Our customers are faced with more opportunity – and risk – than they’ve ever faced before. And they rightfully expect their service providers to cut through the complexity with elegant, powerful tools that meet their goals.

 

Over the course of my first year, I took notes on the core lessons I learned.  Going forward, these notes will serve as my “North Star” as we continue to transform Marketo into an even more global organization that helps companies thrive in what I call the Engagement Economy – a new era that puts the onus on businesses to engage with customers on their terms. And since marketing is far from the only industry facing this level of disruption, I believe these observations will be a useful guide to almost any new CEO.

 

Passion for the Purpose

From minute one on the job, you’ll need to inspire and engage people, rallying them around a purpose. What you’ll find is that no matter how hard you lean in, some people just don’t want to go along for the ride. That’s why the first thing any software company needs is a passionate, engaged team that cares deeply for its customers. They understand that the organization only exists because customers choose to support it, so they must form a team that reflects exactly that level of commitment.

 

One tip for finding those who want to be engaged: Look for people who are passionate about things outside of work. To me, the people who go all-in on their interests outside of the office bring that fire with them inside the office and focus it on finding solutions and serving our customers with an equal sense of fervor.

 

Don’t Let Reality Get in the Way of Opportunity

We’ve all had a similar moment of frustration in a meeting: someone comes up with an idea for a brilliant solution. It elegantly solves a problem and delivers something of real value to your customers. Everyone in the room is excited… until reality smacks you in the face. The reality may be that the timeline for building the product is unrealistic or that there’s no room in the budget to fund it. Or it may be that it doesn’t seem feasible until three other priorities are addressed first.

 

The most common response to this problem is to acknowledge the reality and put the idea on a future “wish list,” ultimately avoiding the tough conversation that is the very thing your team needs you to lead. Don’t take the lazy approach – push harder! The job of the CEO is to push and prod. To dig beneath the surface and empower people to creatively solve problems. Extend your meeting an hour. Challenge your team to not leave the room until a solution emerges. And, most importantly, get right into the trenches with them to help figure it out.

 

Never Be Lukewarm

I can work with people who have a negative attitude. Sometimes they can be a useful foil, forcing me to consider all angles of a problem and come up with better solutions. But I absolutely can’t stand people who are lukewarm. If there’s a fire, I don’t want people who stand there and tell me there’s a fire. Either run toward it and help or get out of the way.

 

I love creative tension. If I’m in a meeting and someone disagrees with my approach, I say bring it. And I try to hold myself to the same standard. If someone brings me an idea or a solution for a challenge they have identified, I don’t want them to walk away from my desk without feeling like we have a resolution or an action plan.

 

Rock the Boat and Challenge Norms

From day one, I made it clear that Marketo team members have an extraordinary opportunity. With our scale, products, and customer base, we can do more than ride the wave of technological change – we can lead it. But we can’t do it if we believe in the old fallacy that the thing that worked yesterday will work tomorrow.

 

In any large organization, you’ll find people who are excited to shake things up and push themselves, their teams, and their companies to be better… and you’ll find others who are generally happy with the status quo and don’t feel any urgency to change. A CEO’s job is to identify those who are willing to take risks, rock the boat and then give them the chance to shine. Promote them to a job that’s just a bit beyond their reach and let them push themselves.

 

Follow the One Lesson That Matters Most

It’s impossible to do all of the things I’ve described without ruffling some feathers.  And that’s ok – if it’s done respectfully and humbly. No CEO should walk around thinking their title means they have all the answers. And even if you come in as a change-maker, make sure to study your company’s history, spend time listening to the team you now lead, and keep an open mind.

 

Ultimately, I’ve found that any CEO is only as good as the people around him or her. Building consensus while boldly leading a new team through change is much easier said than done for any leader. Yet, in this age of disruption, it’s the ultimate measure of almost any CEO’s success. And it leaves us with the one lesson learned that matters most: Be brave. Be fast. Be bold.

 

Steve Lucas is CEO of Marketo. View the original post on LinkedIn.

Dewayne Headshot.pngDewayne is responsible for anything that is fan-facing, from corporate communications to broadcast, in-arena entertainment and retail. He is also responsible for digital and social presence, analytics, creative services and overall brand strategy.

 

In this discussion, Dewayne talks about engaging fans to win, the challenges and benefits of partnerships, and how the Engagement Economy assists him along the way.

Read the full post on CMO Nation.

Cassio.pngCassio is responsible for sales, marketing, supply chain, customer services, and IT.

In this discussion, Cassio talks about how he measures success in the Engagement Economy, how you can personalize the customer experience and the processes that SGI uses to ensure an engaging experience.

Read the full post on CMO Nation.

Stephanie Meyer.png

Stephanie is responsible for PR, IR, marketing operations, and anything that has touchpoints with customers aside from sales.

In this discussion, Stephanie talks about her experiences with the Engagement Economy as a consumer, the biggest challenges CMOs face today, and how to successfully engage with employees.

Read the full post on CMO Nation.

As part of our drive to understand and distill the best thinking from across the marketing world, we have been lucky enough to engage in conversations with senior marketing leaders from a broad range of industries. Through all our discussions, it is clear that certain themes are top-of-mind for many marketers, so we've distilled key insights to share with you here.

Earlier this year, we focused on the rising importance of content. In this conversation, we'll hone in on what it takes to succeed. We'll hear from top CMOs about what success looks like in the Engagement Economy, some of the biggest challenges they face, and the companies they admire for their engagement strategy.

Read the full post on CMO Nation.

Jennifer Dominquini.pngIn addition to being responsible for all the traditional marketing functions, Jennifer is also responsible for digital sales, analytics, and online account origination.

In this discussion, Jennifer talks about the obstacles in the Engagement Economy, how she utilizes partner strategy, and the secret behind good marketing.

Read the full post on CMO Nation.

CEO Steve Lucas created this piece for VentureBeat that was reposted on CMO Nation. See below for a preview, and then click the link at the end to check out the full piece.

 

 

Not long ago, reaching audiences through technologies like email was considered breakthrough. Fast forward to today, a hyper-accelerated existence in which the average human checks their smartphone over 150 times daily.

This phone-fiddling translates into the average enterprise dealing with somewhere between 200 and 300 million digital signals per day, yet most can barely handle about 2 percent of that data. This implies companies attempt to make sense of around 4 million signals every single day—which is still far too many to analyze, interpret, and respond to quickly.

As for the 98 percent of the signals organizations can’t handle, massive amounts of opportunity and insight are lost.

Until now.

AI—whereby machines emulate intelligent behavior—already affects nearly everything you buy, watch, invest in, and more. Most of us can draw on consumer experiences influenced by AI, like Netflix recommendations or suggested purchases from Amazon. These use cases, while consumer-centric, are making their way into the enterprise.

Head to CMO Nation to continue reading.

Filter Blog

By date: By tag: