1

I'm trying to trim some time off of our newsletter sends. We have a daily newsletter that delivers to ~600k subscribers each morning. The content is populated by an RSS feed that is parsed with AMPScript blocks containing numerous IF statements (example included below). The automation currently takes an average of 3+ hours to complete (including a 30 min wait period).

How can I be more efficient with my AMPScript and/or cache elements of the newsletter in order to speed up the automation's processing time?

Note: Each day's newsletter contains 9 - 12 of these blocks of AMPScript to parse different categories of the RSS feed (i.e. Page one, The Nation, etc). The @xml variable is set only once via httpget(), then used throughout the 9-12 blocks.

Any and all thoughts are appreciated! Thanks!

%%[

Var @xml, @title, @image, @link, @desc, @overline, @hide, @i, @rowCount, @Nodes, @none
Set @xml = TreatAsContentArea('RSSCA1',HTTPGet("My RSS url")) /* content area from which the RSS content will be pulled */
Set @Nodes = BuildRowsetFromXML(@xml, "//item[category='Page one']", 1)
Set @rowCount = rowcount(@Nodes)

for @i = 1 to 4 do

    if rowcount(BuildRowsetFromXML(@xml,concat("//item[category='Page one'][",@i,"]/title"),1)) > 0 then
        set @title = Field(Row(BuildRowsetFromXML(@xml,concat("//item[category='Page one'][",@i,"]/title"),1),1),'Value')
    elseif
        rowcount(BuildRowsetFromXML(@xml,concat("//item[category='Page one'][",@i,"]/title"),1)) < 1
    then
        set @none = ';display:none; mso-hide:all'
    endif

    if rowcount(BuildRowsetFromXML(@xml,concat("//item[category='Page one'][",@i,"]/enclosure"),1)) > 0 then
        set @image = Field(Row(BuildRowsetFromXML(@xml,concat("//item[category='Page one'][",@i,"]/enclosure"),1),1),'url_att')
    else
        set @image = 'my backup image'
    endif

    if rowcount(BuildRowsetFromXML(@xml,concat("//item[category='Page one'][",@i,"]/category[position()>1]"),1)) > 0 then
        set @overline = Field(Row(BuildRowsetFromXML(@xml,concat("//item[category='Page one'][",@i,"]/category[position()>1]"),1),1),'Value')
    else
        set @hide = ';display:none;mso-hide:all'
    endif

    if rowcount(BuildRowsetFromXML(@xml,concat("//item[category='Page one'][",@i,"]/link"),1)) > 0 then
        set @link = Field(Row(BuildRowsetFromXML(@xml,concat("//item[category='Page one'][",@i,"]/link"),1),1),'Value')
    endif

    if rowcount(BuildRowsetFromXML(@xml,concat("//item[category='Page one'][",@i,"]/description"),1)) > 0 then
        set @desc = Field(Row(BuildRowsetFromXML(@xml,concat("//item[category='Page one'][",@i,"]/description"),1),1),'Value')
    endif
]%%

<tr>
<td class="two-column" style="padding:0;width:520px;max-width:520px;padding:20px 0;border-bottom:solid 1px #eaeaea %%=v(@none)=%%">
  <!--[if (gte mso 9)|(IE)]>
    <table width="520" align="center" style="padding:0;border-spacing:0;" cellpadding="0" cellspacing="0">
      <tr>
        <td width="200" valign="top" style="max-width:200px;padding:0;border:0;">
  <![endif]-->
  <div class="narrow-column" style="width:38%;max-width:200px;display:inline-block;vertical-align:top;">
    <table style="border-spacing:0 %%=v(@none)=%%">
      <tr>
        <td style="padding:0;">
          <a href="%%=RedirectTo(@link)=%%" target="_blank" style="color:#000000;text-decoration:none;"><img class="image" src="%%=v(@image)=%%" width="200" style="border:0;width:100%;max-width:200px;"></a>
        </td>
      </tr>
    </table>
  </div>
  <!--[if (gte mso 9)|(IE)]>
  </td>
  <td width="305" valign="top" style="max-width:305px;padding:0;border:0;">
  <![endif]-->
  <div class="wide-column" style="width:58%;max-width:305px;display:inline-block;vertical-align:top;">
    <table style="border-spacing:0 %%=v(@none)=%%">
      <tr>
        <td class="text" style="padding:0;padding-left:15px;">
          <p class="overline" style="Margin:0;font-family:Helvetica, arial, sans-serif;font-size:10px;line-height:12px;font-weight:normal;text-transform:uppercase;text-align:left;color:#870413%%=v(@hide)=%%"> %%=v(@overline)=%%
                                    </p>
          <p class="headline" style="Margin:0 0 5px 0;font-family:Helvetica, arial, sans-serif;font-size:22px;font-weight:bold;line-height:28px;"><a href="%%=RedirectTo(@link)=%%" target="_blank" class="headline-link" style="color:#000000;text-decoration:none;"> %%=v(@title)=%%</a>
          </p>

          <p class="copy" style="Margin:0;font-family:Georgia, Times New Roman, serif;font-size:13px;font-weight:normal;line-height:18px;">%%=v(@desc)=%%  <a class="continue" href="%%=RedirectTo(@link)=%%" target="_blank" style="color:#000000;text-decoration:underline;color:#127694;"> Continue reading &rarr;</a>
          </p>
        </td>
      </tr>
    </table>
  </div>
  <!--[if (gte mso 9)|(IE)]>
  </td>
</tr>
</table>
  <![endif]-->
</td>
</tr>

%%[ NEXT @i ]%%

Update 5/10/17: I ended up "solving" the processing time issue by breaking the list into smaller segments, which sped up the time to send. Not a perfect solution by any means, but one that worked for our purposes.

2

I'd look into off-loading the caching/parsing of the RSS data into a SSJS Script Activity that writes it to a Data Extension.

Then in your email, you can just do a lookup and iterate through the rows, displaying the HTML for each one.

1
  • Hi Adam, thanks for the suggestion. I'm sure this would work, unfortunately I'm not familiar enough with Server Side Java Script to implement the solution at the moment.
    – Jeff Ayers
    May 10 '17 at 13:30
1

Looking at your code, it seems pretty much all 600k subscribers get the same content. I see you're caching the HttpGet by using TreatAsContentArea, but you still have a large number of expensive operations that you're executing 600k times - BuildRowSetFromXML etc.

Take more or less the entirety of the above, place it in a Content Area and then call that Content Area from your email using TreatAsContentArea.

You should be able to send millions per hour that way.

7
  • Hi Andrew, thanks for the help! In the original version of this email I had a main template that called content areas based on the day of the week (each day has different sections/requirements). Each content area contained a version of the code above. For example: if @pubDate == 'Mon' then set @content = ContentAreaByName("My Contents\TH RSS Blocks\TH RSS TEST Blocks\Monday TEST") So if I wrap that ContentAreaByName function in a TreatAsContentArea(), would that do the trick?
    – Jeff Ayers
    May 4 '17 at 13:00
  • Or do you mean when I call the content block with the %%=v(@content)=%% I should instead use %%=TreatAsContentArea('CA' , v(@content))=%% ?
    – Jeff Ayers
    May 4 '17 at 13:04
  • Hey Jeff. Yes. Wrap that ContentAreaByName in a TreatAsContentArea() and you'll notice a marked improvement. I did similar with a client with similar volumes and time to send to you and ended up reducing 3.5 hours to 7 minutes. The email crashed their website with the spike in activity and the conversation moved to Send Throttling... LOL.
    – Macca
    May 4 '17 at 13:09
  • haha a far better problem to have! I'll do what you've suggested and report back. Any chance you know of a way to check time to send without, you know, actually sending a live email to 600k people...
    – Jeff Ayers
    May 4 '17 at 13:12
  • Either of your formulations amounts to the same thing.
    – Macca
    May 4 '17 at 13:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.