$30 off During Our Annual Pro Sale. View Details »

Mastering Email with Ruby

October 08, 2015

Mastering Email with Ruby

E-Mail persists after many decades and will also survive the next hyped communication technology. Despite being a pest, E-Mail is also an effective marketing channel and one of the most personal communications you have with your users and customers. 

Responsive E-Mail HTML is not as difficult as many think. We'll look at some common problems with solutions for developing bulletproof E-Mails. But most importantly we'll look at how programming workflow is just as important and how I use Ruby to do that.


Notes: This online PDF has a few more slides than the presented version, to explain a screenshot or some code.


October 08, 2015

More Decks by jng

Other Decks in Programming


  1. Mastering Email with Ruby Julie Ng RubySauna
 Helsinki, Finland 8

    October 2015
  2. Julie Ng • American Developer in Munich • Previously Designer

    at ancestry.com for European Markets • UX Email Developer, Consultant • Refresh Munich e.V. Chairwoman • Runner, Climber
  3. Email != hard

  4. 1. More Code 
 required to create bulletproof emails 2.

    Extra Build Step
 inline css - thanks Google! 3. Manage shared code? 
 no best practice conventions when shared CSS Email is tedious
  5. Email Cut Offs Source: Neil Bursnoll, Adestra adestra.com/avoid-gmail-clipping-emails Source: Geoff

    Phillips, Email on Acid emailonacid.com 102 kb Gmail Web Source: Ros Hodgekiss, Campaign Monitor campaignmonitor.com 20 kb Gmail iOS 15 kb Mail iOS
  6. Email = more HTML

  7. Image <img src="<%= source %>" border="0" alt="<%= alt %>" <%=

    " width=\"#{width}\"" if defined? width %> <%= " height=\"#{height}\"" if defined? height %> <%= " align=\"#{align}\"" if defined? align %> <%= " styles=\"#{styles}\"" if defined? styles %> <%= " class=\"#{klass}\"" if defined? klass %> hspace="0" vspace="0" > *required for Outlook
  8. Bulletproof = more code and

  9. Button <table border="0" cellspacing="0" cellpadding="0" class="button yellow" align="center"> <tr> <td

    align="center"><a href="http://juile.io/"><!--[if mso]>&nbsp;<![endif]-->A button →<!--[if mso]>&nbsp;<![endif]-- ></a></td> </tr> </table> Note: no whitespace in code between <td></td> for Outlook
  10. Button (inlined) <table border="0" cellspacing="0" cellpadding="0" class="button yellow" align="center" style="margin-left:auto;margin-

    right:auto"> <tr> <td align="center" style="-webkit-border-radius:3px;-moz- border-radius:3px;border-radius:3px;background- color:#2095F2;background-color:#f1c40f;border- color:#dab10d;color:#6F4F1D"><a href="http://juile.io/" style="-webkit-border-radius:3px;-moz-border-radius:3px;border- radius:3px;font-weight:bold;font-size:14px;line-height: 20px;font-family:Helvetica, Arial, sans-serif;text- decoration:none;display:inline-block;padding:12px 18px;border: 1px solid #0e89eb;background-color:#2095F2;background- color:#f1c40f;border-color:#dab10d;color:#6F4F1D"><!--[if mso]>&nbsp;<![endif]-->A button →<!--[if mso]>&nbsp;<![endif]-- ></a></td> </tr> </table>
  11. Tables for Layouts

  12. Grid with <table>s <!--[if mso]><table><tr><td width="300"><![endif]--> <table align="left" width="100%" style="max-width:300px">

    … Column 1 … </table> <!--[if mso]></td><td width="300"><![endif]--> <table align="left" width="100%" style="max-width:300px"> … Column 2 … </table> <!--[if mso]></td></tr></table><![endif]-->
  13. You can use <th> instead of <td> Can use display:block!

    on <th> for responsive layouts. But seems wrong to me.
 You can use Margin:5px; instead of margin:5px; But then beware of CSS inliners (more later) Bulletproof = NO hacks
  14. Defensive Coding <table style="font-family:Helvetica;"> <tr> <td> this will not be

    in Helvetica :( </td> </tr> <tr> <td style="font-family:Helvetica;"> but this will :) </td> </tr> <tr> <td style="font-family:Helvetica;"> I will be Helvetica <img> Me too. But I might be purple in Gmail. </td> </tr> </table>
  15. None
  16. Tedious Builds

  17. Compile CSS Concatenate HTML Upload images Build OK, it's not

    that hard…
  18. Tedious Builds Inlining CSS = Tedious

  19. 1. Inlined CSS
 (Thank you Gmail) 2. Included CSS CSS

    Resets Desktop resets (e.g. grids) Media Queries for responsive layouts 2 Layers of CSS Same, same, but different is hard
  20. CSS Inliners Compared Styliner Juice Premailer Roadie Language JavaScript JavaScript

    Ruby Ruby GitHub Favorites 91 895 1466 865 GitHub Issues 6 10 93 4 Affects Markup? ? sometimes… sometimes… Nokogiri… Shorthand CSS? ? Yes Yes No Respects HTML Comments? ? ? ? Yes Respects <style>? ? Supposed to Yes Sometimes? Check issues. Try it. Stats from September 2015
  21. Not all CSS is inlined <style> /* Do not inline!

    iOS autolinks */ .ios-footer a { color: #999999 !important; } </style> <span class="ios-footer"> MyCompany.com 123 Main St Springfield, MA </span>
  22. <style> to inline or not? Source https://github.com/premailer/premailer/issues/242

  23. Bug: Removed Comments Source https://github.com/premailer/premailer/issues/238

  24. No shorthand CSS .example { /* This works across all

    clients */ background-color: #ff0000; background-image: linear-gradient(#111111, #222222 50%, #111111); /* But the same as shorthand does not because Outlook does not understand linear-gradient, so ignores all values for background. */ background: #ff0000 linear-gradient(#111111, #222222 50%, #111111); }
  25. Do not change or adjust HTML Preserve comments (esp. if

    mso) Do not use CSS shorthand Inline some styles, but not others. Include some styles, but not others. CSS Inliner Checklist
  26. A Build System

  27. Inline and include CSS without mistakes Build partials Preserve Logic

    Workflow Wishlist
  28. Templates, support for partials Development preview Inlines CSS (Premailer) Missing:

    options for individual stylesheets build partials preserve logic grunt-email-workflow grunt-email-workflow github.com/leemunroe/grunt-email-workflow
  29. Can use Front Matter for custom stylesheets Has useful content_for

    helper Has Live Preview Missing: inlined CSS build partials preserve logic Middleman Middleman middlemanapp.com
  30. Why Partials? <table> <tr> <td class="t-1st">Item</td> <td>Qty</td> <td class="t-last">Subtotal</td> </tr>

    <% @config.products.each do |product| %> <%= partial :product, locals: product %> <% end %> </table> <tr class="prod"> <td class="p-img t-1st"><%= image_tag url %></td> <td><%= title %></td> <td><%= quantity %></td> <td class="p-eur t-last"><%= price %></td> </tr> TEMPLATE PARTIAL
  31. emails are more than just newsletters. have re-usable components. we

    can easily port inlined partials with preserved logic into any backend framework you use. 
 Just because email is more tedious, it doesn't mean we can't apply general development best practices. Partials because…
  32. Faster Workflow with Ruby

  33. 1. Development 2. Upload Images 3. Inline CSS 4. Send

    Email 5. Test/Debug 6. Rinse and Repeat Workflow
  34. demo Screenshots

  35. Inlined Partial with Preserved Logic

  36. Preserved Logic
 with Regular Expressions

  37. None
  38. None
  39. Example: Complex Partial

  40. None
  41. My Custom Workflow

  42. None
  43. None
  44. 1. Development: sinatra, sass, rack-livereload 2. Upload Images: fog, aws

    3. Inline CSS / Build HTML: roadie, Regular Expressions 4. Send Email: mail 5. Test/Debug 6. Rinse and Repeat Workflow
  45. Julie Ng @jng5 julie.io Fin