SOLVED

Re: Extracting Values from a Custom Object Field - Velocity Token

Go to solution
Anonymous
Not applicable

Extracting Values from a Custom Object Field - Velocity Token

Greetings,

I have the following custom object called 'ProductInterest' in our CRM, this object includes a number of values, one of which is productName. A client can have multiple products (ProductName). If I drag and drop the field to the token script area, it shows as ${ProductInterestList.get(0).ProductName}

productinterest.png

I am trying to write a Velocity Script Token to display an image based on what Products (ProductName) they are a member of. Token name is {{my.image}} and in the email I am calling it something like this

<img src="{{my.image}}" alt="">

The Velocity Script Token:

#if( $ProductInterest.ProductName == 'product1' || $ProductInterest.ProductName == 'product2' || $ProductInterest.ProductName == 'product3' )

http://www.myurl.com/images/Banner1.jpg

#else

http://www.myurl.com/images/Banner2jpg

#end

This is not working, the result is always Banner2 (the #else image) when testing on a lead that has either product 1, 2 or 3 only... any idea's?

(I even tried

#if( $ProductInterest.ProductName == 'product1' )

#elseif( $ProductInterest.ProductName == 'product2' )

#elseif( $ProductInterest.ProductName == 'product3' )

http://info.lazardnet.com/rs/211-JCD-267/images/Banner factsheet EMD_II.jpg

#else

http://info.lazardnet.com/rs/211-JCD-267/images/Banner factsheet.jpg

#end)

1 ACCEPTED SOLUTION

Accepted Solutions
SanfordWhiteman
Level 10 - Community Moderator

Re: Extracting Values from a Custom Object Field - Velocity Token

Ed, I'd use an extensible approach like so:

## Set up your map of products to related asset(s)

#set( $assetsByProduct = {

  "product1|product2|product3" : {

    "banner" : "BannerA.jpg"

  },

  "product4|product5" : {

    "banner" : "BannerB.jpg"

  },

  "product6|product7|product8" : {

    "banner" : "BannerC.jpg"

  },

  "" : {

    "banner" : "DefaultBanner.gif"

  }

} )

##

## Start w/default asset set (empty key)

#set( $assets = $assetsByProduct[""] )

##

## Guard against bad inputs (null or empty object list)

#if( $ProductInterestList && !$ProductInterestList.isEmpty() )

    ##

    ## Loop backwards through objects (standard foreach is fwd only)

    #foreach( $idx in [$math.sub($ProductInterestList.size(),1)..0] )

        #set( $interest = $ProductInterestList[$idx] )

        #foreach( $assetSet in $assetsByProduct.keySet() )

            ##

            ## If we find a regex match for [map key,ProductName] we're done

            #if( $interest.ProductName.matches("(?i)${assetSet}") )

                #set( $assets = $assetsByProduct[$assetSet] )

                #break($foreach.parent)

            #end

        #end

    #end

#end

<img src="http://www.example.com/rs/${assets.banner}">

It's actually very simple logic, but Velocity is wordy (the same concept in JS would be half as long, for example there you have Array#reverse() while in VTL that doesn't exist as a built-in function).

The gist is:

  • set up a mapping object that pairs product(s) with their banner images; use a default key ("") for when there's no match
  • scan all the lead's ProductInterest objects -- from last to the first
  • as soon as you get a pattern match, that's where you get your banner

It's extensible because you can add any other ProductInterest-specific data you want -- not just the "banner" property, but any other data that goes with the product. The $assetsByProduct map could be in its own script token for modularity.

Note the code uses a naive ordering to loop backward through the custom objects by index. You might want to sort them by some other property.

Final note: I added tabs for visual clarity. You'll want to delete them from your token (whitespace in Velocity doesn't disappear on its own, you may recall from other posts).

View solution in original post

12 REPLIES 12
Grégoire_Miche2
Level 10

Re: Extracting Values from a Custom Object Field - Velocity Token

Hi Ed,

ProductInterest is a multi record array, since by design there is a 1-N relationsgip between leads and ProductInterest.

Hence the notation ${ProductInterestList.get(0).ProductName} that returns the first occurence of Producs interest for the lead.

#if( ${ProductInterestList.get(0).ProductName} == 'product1' || ${ProductInterestList.get(0).ProductName} == 'product2' || ${ProductInterestList.get(0).ProductName} == 'product3' )

http://www.myurl.com/images/Banner1.jpg

#else

http://www.myurl.com/images/Banner2jpg

#end

You could also store ${ProductInterestList.get(0).ProductName} in a variable and test this variable

#set($ProductInterest = ProductInterestList.get(0).ProductName)

#if( $ProductInterest == 'product1' || $ProductInterest == 'product2' || $ProductInterest == 'product3' )

http://www.myurl.com/images/Banner1.jpg

#else

http://www.myurl.com/images/Banner2jpg

#end

Also, please remember that if you have more than 1 product interest for a lead, only the ten most recently updated objects of a type are loaded. The list is ordered from most to least recently updated record.

-Greg

Anonymous
Not applicable

Re: Extracting Values from a Custom Object Field - Velocity Token

Hi Greg,

Thank you for the prompt reply, I have tried

#set($ProductInterest = $ProductInterestList.get(0).ProductName)

#if( $ProductInterest == 'product1' || $ProductInterest == 'product2' || $ProductInterest == 'product3' )

http://www.myurl.com/images/Banner1.jpg

#else

http://www.myurl.com/images/Banner2jpg

#end

Still only returning the second Banner. I have double checked the lead I am testing has Product 1 and should receive Banner1

Grégoire_Miche2
Level 10

Re: Extracting Values from a Custom Object Field - Velocity Token

Sanford Whiteman

this is for you

-Greg

Anonymous
Not applicable

Re: Extracting Values from a Custom Object Field - Velocity Token

Ok after double checking the Lead, it seems he had product 1, product 2, product 3 and product 4 so the logic I presume is taking the last product he has (product4) and returning the "#else" for banner 2. When I added product 4 to the If statement it returned the right Banner. So the question is how do I re-write the code to check if a lead has 'either product 1, 2 or 3' even if they have other products, to display banner 1?

Grégoire_Miche2
Level 10

Re: Extracting Values from a Custom Object Field - Velocity Token

Hi Ed,

You will have to iterate through the values (Attention, Velocity will only process the 10 most recent, even if a lead has more than 10), set a flag and test the flag after the loop.

Look here for some examples: http://developers.marketo.com/email-scripting/examples/

-Greg

Anonymous
Not applicable

Re: Extracting Values from a Custom Object Field - Velocity Token

Thanks again Greg..

Will do the research, atleast now I am on the right track, again appreciate the help...

SanfordWhiteman
Level 10 - Community Moderator

Re: Extracting Values from a Custom Object Field - Velocity Token

I'll put up some code lat'ron. There's a pretty concise way to do this.

SanfordWhiteman
Level 10 - Community Moderator

Re: Extracting Values from a Custom Object Field - Velocity Token

Ed, I'd use an extensible approach like so:

## Set up your map of products to related asset(s)

#set( $assetsByProduct = {

  "product1|product2|product3" : {

    "banner" : "BannerA.jpg"

  },

  "product4|product5" : {

    "banner" : "BannerB.jpg"

  },

  "product6|product7|product8" : {

    "banner" : "BannerC.jpg"

  },

  "" : {

    "banner" : "DefaultBanner.gif"

  }

} )

##

## Start w/default asset set (empty key)

#set( $assets = $assetsByProduct[""] )

##

## Guard against bad inputs (null or empty object list)

#if( $ProductInterestList && !$ProductInterestList.isEmpty() )

    ##

    ## Loop backwards through objects (standard foreach is fwd only)

    #foreach( $idx in [$math.sub($ProductInterestList.size(),1)..0] )

        #set( $interest = $ProductInterestList[$idx] )

        #foreach( $assetSet in $assetsByProduct.keySet() )

            ##

            ## If we find a regex match for [map key,ProductName] we're done

            #if( $interest.ProductName.matches("(?i)${assetSet}") )

                #set( $assets = $assetsByProduct[$assetSet] )

                #break($foreach.parent)

            #end

        #end

    #end

#end

<img src="http://www.example.com/rs/${assets.banner}">

It's actually very simple logic, but Velocity is wordy (the same concept in JS would be half as long, for example there you have Array#reverse() while in VTL that doesn't exist as a built-in function).

The gist is:

  • set up a mapping object that pairs product(s) with their banner images; use a default key ("") for when there's no match
  • scan all the lead's ProductInterest objects -- from last to the first
  • as soon as you get a pattern match, that's where you get your banner

It's extensible because you can add any other ProductInterest-specific data you want -- not just the "banner" property, but any other data that goes with the product. The $assetsByProduct map could be in its own script token for modularity.

Note the code uses a naive ordering to loop backward through the custom objects by index. You might want to sort them by some other property.

Final note: I added tabs for visual clarity. You'll want to delete them from your token (whitespace in Velocity doesn't disappear on its own, you may recall from other posts).

Anonymous
Not applicable

Re: Extracting Values from a Custom Object Field - Velocity Token

Again a perfect solution, Thank you again for a detailed and well explained reply... This can easily be your next blog post!