Adobe Campaign documentation is great to build 2-3 web apps. But itโ€™s absolutely not scalable in case you need to develop 25-30 web apps with a lot of assets (CSS, JS, Images). Here are some best practices for web development in AC7.

Use Bootstrap

For every web apps youโ€™ll ever use, use the following boiler plate code:

<!DOCTYPE html>
<html lang="en">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- Title -->
    <!-- favicon -->
    <link href="<%= getOption('RESOURCES_URL') %>favicon.ico" rel="icon"><!-- see next chapter for 'RESOURCES_URL' -->
    <link href="<%= getOption('RESOURCES_URL') %>favicon.ico" rel="shortcut icon"/> 
    <link href="<%= getOption('RESOURCES_URL') %>favicon.png" rel="shortcut icon" type="image/png"/>
    <!-- Common CSS -->
    <link rel="stylesheet" href="">
    <link rel="stylesheet" href="<%= getOption('RESOURCES_URL') %>base.css"><!-- see next chapter for 'RESOURCES_URL' -->
    <!-- Custom CSS -->
    <link rel="stylesheet" href="<%= getOption('RESOURCES_URL') %>my-layout.css">
    <style type="text/css" media="all">
      /* always keep an inline <style> for quick edit by designers */

  <body class="container"><!-- or .container-fluid, see -->
    <!-- Common JS -->
    <script src="" type="text/javascript"></script>
    <link rel="stylesheet" href="<%= getOption('RESOURCES_URL') %>base.js">
    <link rel="stylesheet" href="<%= getOption('RESOURCES_URL') %>google-analytics.js">
    <!-- Custom JS -->
    <link rel="stylesheet" href="<%= getOption('RESOURCES_URL') %>my-page.js">

In short you have the following:

  • Use modern HTML template from
  • Always separate you common assets (common to all web apps), from the custom assets (on a per case basis)
  • Donโ€™t include jQuery as it will be automatically added by Adobe Campaign itself. Adobe Campaign 7 will by default import:
    • jQuery 1.9.1. Note: jQuery is available via jQuery and not with $.
    • jQuery-migrate 1.1.1
    • spin.js 2.3.2
    • JSON2 polyfill
  • A Google analytics easy set up, to capture traffic
  • Use a global option for the Adobe Campaign Resources CDN, see below

Organize your assets

Create a global option RESOURCE_URL

Adobe Campaign gives us the ability to get the Online Resources URL in JavaScript with xtk.fileRes.GetPublicFileResURL(). Call it in a workflow or get it from a Resource:

Replace http by https and use it in an Option:

Use filename instead of md5

By default, every File Resource will be given a Public URL based on itโ€™s md5 content:

This is absolutely not what we want. If you change the image, the md5 will change as well, so youโ€™ll have to change it in all your webappsโ€ฆ Which means for every CSS change, youโ€™d have to edit the Public URL ๐Ÿ˜ต.

Instead, we can ask Adobe Campaign to use the Filename in place of the md5 hash. Uncheck the checkbox in the advanced parameters of the resource:


This way, we just made Web development in AC great again!

<!-- CSS -->
<link rel="stylesheet" href="<%= getOption('RESOURCES_URL') %>style.css">
<!-- JS -->
<script src="<%= getOption('RESOURCES_URL') %>script.js" type="text/javascript"></script>
<!-- Image -->
<img src="<%= getOption('RESOURCES_URL') %>loader.svg"/>

And with this new markup, you are able to migrate very easily from your Staging/Dev Environment to your Production Environment. Weโ€™re now #DRY compliant. Sweeeeet ๐Ÿก๐Ÿญ๐Ÿฌ

Sharing meta data (Facebook opengraph og, Twitter card, Google result)

Ever tried to share a web app in Facebook?

Update your workflow by adding a JavaScript activity right before the first page:

Use this JS code:

ctx.sharing.title = "Title for Social Media" = "Author"
ctx.sharing.description = "Social description"
ctx.sharing.image = "https://Public image URL used for sharing"

and in your HTML:

<!DOCTYPE html>
<html lang="en">
    <!-- Title -->
    <!-- meta For Google -->
    <meta name="description" content="<%= ctx.sharing.description %>" />
    <meta name="keywords" content="" />
    <meta name="author" content="<%= %>" />
    <meta name="copyright" content="" />
    <meta name="application-name" content="" />
    <!-- meta For Facebook -->
    <meta property="og:title" content="<%= ctx.sharing.title %>" />
    <meta property="og:type" content="article" />
    <meta property="og:image" content="<%= ctx.sharing.image %>" />
    <meta property="og:url" content="" />
    <meta property="og:description" content="<%= ctx.sharing.description %>" />
    <!-- meta For Twitter -->
    <meta name="twitter:card" content="summary" />
    <meta name="twitter:title" content="<%= ctx.sharing.title %>" />
    <meta name="twitter:description" content="<%= ctx.sharing.description %>" />
    <meta name="twitter:image" content="<%= ctx.sharing.image %>" />
    <!-- Common CSS -->

  <body class="container"><!-- or .container-fluid -->

You can test your markup for Facebook on