A module for distributing and managing ads locally on an Express web site
JavaScript CSS
Switch branches/tags
Clone or download


Express Ads

Express Ads provides a lightweight simple way to deliver ads in an Express-based web site. It works with any template engine and provides a nice admin interface.

Live demo

Visit demo.eas.rocks . The full source code of the live demo site is available from github. It may be useful to better understand how to implement express-ads in your web site.


  • Multiple concurrent campaigns
  • Multiple banners per campaign
  • Multiple creatives per banner
  • Several campaign types:
    • Number of prints within a period
    • Number of click within a period
    • Recurrent prints (like 10000 prints per day)
    • Recurrent clicks (like 100 clicks per day)
    • Background (weighted display on available inventory)
  • Ads are distributed evenly over the period
  • Page and session capping per banner and/or campaign
  • Country/OS/Browser filtering
  • Campaign optional start/end dates
  • Real time prints and clicks statistics
  • Full admin interface integrable to the site's existing admin
  • Not relying on a specific database
  • Robust to ad-blockers (ads served from the site itself)
  • Extensible via add-ons to serve ads for external platforms


ScreenShot ScreenShot

Using Express Ads (short version)

App setup

var app = express();
app.get('/content-path', function (req, res) {
	res.render(someTemplate, { 
		ad: req.deliverAd,

Requesting an ad

Using Jade as template engine

  | Ipsum lorem ...
| !{ ad('area-name') }
  | Ipsum lorem ...

Using EJS as template engine

<p>Ipsum lorem ...</p>
<%- ad('area-name') %>
<p>Ipsum lorem ...</p>

From the admin interface

  • Open `http://your-domain.com/eas/admin'
  • Create an area specifying the size
  • Create a banner
  • Add the area to the banner
  • Setup the banner link
  • Add one or more images to the banner with same size
  • Create a campaign
  • Add the banner to the campaign
  • Reload the content page, ads should be displayed

Using Express Ads (detailed version)

Setting up in your web site

Setup express-ads in your application using:

var app = express();

after doing so, the req object will contain the following new fields:

  • deliverAd: a function that returns the HTML code to display (or not) an ad
  • expressAds: access to global express-ads service

deliverAd takes 2 parameters: areaName and an optional adParams and returns immediately the HTML code for the ad to display. Note that it might be an empty string if the module decided that no ad should be displayed.

  • areaName is the human name of an area that must have been created from the admin interface
  • adParams an object with the following fields:
Param Default Description
styles null an object containing CSS styles and values to display the ad container
classes null an array of classes (as strings) to be applied to the ad container
tag null if set, the HTML element to be used for the ad container. By default, <p> is used for text inventory areas, <div> for other inventory types

Note that those parameters (styles, classes, tags) can also be set tuned from the admin interface. It's up to you to choose whatever styling method you want to use.

expressAds is an object that provides access to a number of services:

Param Description
adminUI a function that returns the entire admin interface HTML code
styles an array of strings representing the stylesheets to be included in the admin page
stylesHTML like styles formatted as a single HTML string that loads the stylesheets
scripts an array of strings representing the scripts to be included in the admin page
scriptsHTML like scripts formatted as a single HTML string that loads the scripts
saveStats a function to save manually the current stats. It takes a callback as parameter that is called when the save operation is done. Note that stats are automatically saved every minute, so this function is only useful when doing a shutdown of the application if you don't want to lose the last minute of stats

When doing require('express-ads')(app,options), options is an object that can contain the following fields:

Param Default Description
path "/eas" the base URL path where express-ads services are attached to
adminPath null by default (null), the express-ads admin interface can be accessed from path+/admin (if you did not change path, it is /eas/admin). You can set adminPath to any other path value, like "/admin/eas"
auth passthrough function a function(req,res,next) to authenticate the access to the express-ads admin interface. By default, this function is a passthrough (it calls next() directly). You can implement your own authenticator here (using passport for instance) or rely on your site's default security system to protect the path to the admin page. For instance, many sites protect globally everything under /admin, so if you define adminPath to "/admin/eas", you are safe and you can set the auth function to function(req,res,next) { next(); }
staticMaxAge "1h" the cache duration for static resources
rollBacklog 1000 the service maintains a cache for the last events, so it can determine a statistical event rate used to serve ads evenly over a period
rollExpire 172800000 default corresponds to 2 days. Older entries are removed from the roll cache
adblockerDetection true whether the adblocker detection is activated. You can filter banners based on whether the user has an adblocker or not
files an object containing various data pathes (see below)
files.ads "ads.json" file where ads configuration data are kept
files.stats "stats.json" file where stats are kept
files.images "ads/images" directory where banner images are stored
files.tmp "ads/tmp" directory where banner images are temporarily stored
debugDeliver false if set to true, traces are printed to the console when an ad is to be picked for delivery
debugData false if set to true, the admin interface will display an additional containing the raw JSON data for ads config and stats
debugLiveTemplate false if set to true, it won't be necessary to restart the server app to see changes in the admin user interface
imageMagick false use ImageMagik to manipulate banner images. On Ubuntu, you can install ImageMagick with apt-get install imagemagick
addons null an array of add-on modules. See below Extending express-ads
allowedSizes see below an object describing the available inventory areas sizes. A new size can be added by specifying a corresponding entry in allowedSizes, for instance "123x456":1. An existing size can be removed by setting its value to 0: "468x60":0
allowUpload true is uploading local image files allowed

plus a number of parameters dedicated to integrating the express-ads admin interface to the site's admin (see below).

The default value for allowedSizes is:

		allowedSizes: {
			"120x240": 1,
			"120x600": 1,
			"120x60": 1,
			"120x90": 1,
			"125x125": 1,
			"160x600": 1,
			"180x150": 1,
			"234-60": 1,
			"240x400": 1,
			"250x250": 1,
			"300x250": 1,
			"336x280": 1,
			"468x60": 1,
			"728x90": 1,
			"88x31": 1,

Note that additional sizes declared by addons are automatically made available.

Display an ad in the template

Whether you use Jade, EJS or any other templating system, you need to have access from your template to the express-ads deliverAd function:

app.get('/content-path', function (req, res) {
	res.render(someTemplate, { 
		ad: req.deliverAd,

You can then request the ad display doing !{ ad('area-name') } (Jade) or <%- ad('area-name') %> (EJS).

It is a better practice to pass the styling options to the express-ads API <%- ad('area-name',{classes:['ad-wrapper']}) %>, rather than providing your own externally <div class='ad-wrapper'><%- ad('area-name') %></div> because if no ad is to be displayed (ad() returning an empty string) you might be left with unwanted paddings, margins, borders, ...

Express-ads admin interface integration

By default, once express-ads is setup in your site, you can access the admin interface on http://mysite.com/eas/admin, however, since your site is likely to have its own admin user interface, you may want to integrate express-ads into it to keep a common look and feel.

The idea is to provide your own admin template and layout and insert it into your page:

app.get('/admin/ads-management', function (req, res) {
	res.render('ads-management-template, { 
		expressAds: req.expressAds,

and in the template (Jade version):

    | !{ expressAds.adminUI() }
    | !{ expressAds.scriptsHTML }
    | !{ expressAds.stylesHTML }

or (EJS version):

    <%- expressAds.adminUI() %>
    <%- expressAds.scriptsHTML %>
    <%- expressAds.stylesHTML %>

expressAds.adminUI() returns as a single string the whole required HTML to build the user interface, expressAds.scriptsHTML and expressAds.stylesHTML contains the scripts and styles for this page to run.

The express-ads admin page makes use of several common libraries that you may already have setup in your site template. You can prevent the scripts and styles to be loaded twice by specifying parameters adminScripts and adminStyles into options when calling require('express-ads')(app,options).

The admin UI integration specific option parameters are:

Param Default Description
standaloneAdminUI true if set to false a default admin page is not provided
adminScripts see below an object to change or remove loaded scripts
adminStyles see below an object to change or remove loaded styles

For instance, calling require('express-ads')(app,{adminScripts:{jquery:null}) ensures expressAds.scriptsHTML does not contain the code to load jquery, assuming it is loaded by your own means.

The default list of scripts libraries is:

Library value
jquery https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js
angular https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.8/angular.min.js
angularSanitize https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.8/angular-sanitize.min.js
bootstrap https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/js/bootstrap.min.js
moment https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.10.6/moment.min.js
bootstrapDateTimePicker https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/4.17.37/js/bootstrap-datetimepicker.min.js
uiSelect https://cdnjs.cloudflare.com/ajax/libs/angular-ui-select/0.13.2/select.min.js

For styles:

Library value
fontAwesome https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.5.0/css/font-awesome.min.css
bootstrap https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.min.css
bootstrapDateTimePicker https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/4.17.37/css/bootstrap-datetimepicker.min.css
uiSelect https://cdnjs.cloudflare.com/ajax/libs/angular-ui-select/0.13.2/select.min.css

You can see an example of express-ads admin page integration in the exskel (a skeleton for Express-based web sites).

Using the admin interface

This is pretty straight forward.

Basically you create an inventory area, specifying a size. Then, you create a banner, specifying type Image, fill-in details, including a target link, indicate which areas this banner can be displayed to, add images to the banner (only images with a size that fit an inventory area will be used), specify filters if you want to. Next, create a campaign, specifying a type, for instance, Background, the banners you want to use for this campaign and you are all set, express-ads should start delivering ads.

There are a few things that may not be obvious though.

When using a Text banner, that may contain several texts to be chosen randomly, if you simply specify a text like This is the text of my ad, the whole sentence will appear as a link. If you do This is the [[text]] of [[my ad]], text and my ad will appear as links (to the target link you specified for the banner), while the remaining words will show up as normal text.

When specifying a target link for a banner, you can use the following placeholders:

Placeholder Replaced with
{{INV}} the inventory area id
{{CAM}} the campaign id
{{BAN}} the banner id
{{IMA}} the creative (specific image or text) id
{{ALL}} equivalent to {{INV}}.{{CAM}}.{{BAN}}.{{IMA}}

Extending express-ads

Express-ads can be extended using add-ons. There are currently 2 add-ons modules:

Using an express-ads add-on

When calling require('express-ads')(app,options), options must contain fields addons with an array of add-on modules as value. For instance:

	addons: [ require('express-ads-adsense'), require('express-ads-chitika') ] 

When creating a new banner, additional types will be available, in this case AdSense and Chitika. Depending on the add-on requirement, you may have to setup addtional configuration from the admin interface, like the publisher ID and slot ID, either globally from the Express Ads tab, or per banner in the banner settings panel.

Developing an add-on

If you want to develop an add-on for another platform, the good news is that it is very simple. The best way is to start from an exiting add-on like the one for AdSense.

Rename adsense.js to something more appropriate, and edit the file to match your needs. exports.settings and exports.bannerSettings define the settings for the add-on, repectively globally and per-banner. There are 3 parameter types you can use:

Parameter Description
text a single line text parameter
longtext a text over several lines
checkbox a checkbox parameter

The file template.ejs describes (in EJS templating language) the HTML code that will be generated.

When you define a parameter with name, say myparam in settings, it's value is available from the template using <%= settings.myparam %>. If defined in bannerSettings, you can read it as <%= banner.addon.myparam %>.

Other variables are also available in the template:

Parameter Description
size an object with field width and height corresponding to the current area
campaign the full campaign object
banner the full banner object
inventory the full inventory object


  • Express Ads is not intended to support multiple users editing ads from the admin interface at the same time
  • In this early version, only plain images and text ads are supported, not videos. Add-ons allow serving ads from external platforms

Supporting Express Ads

This code is free for you to use. However, in order to ensure we can maintain it, we display an ad from us with a 1% probability on your non-text inventory. We ensure that the ads we display are clean and safe for any environment. Contact us contact at eas.rocks if you have a problem with that.