rack-campaign
This is a Rack application (a gem is available by the same name) allowing you to maintain a YAML file of short URLs that redirect to target URLs with a set of specified Google Analytics variables. It could be used to attach any number of parameters by any name to the query string.
What it does:
example promo url:
http://zetetic.net/c/blog-rack-campaign
When the user visits this link, our web server sees the /c/ location and forwards it to rack-campaign, which looks up ‘blog-rack-campaign’ in the YAML file, and redirects the user to the full URL, with campaign variables attached.
resulting full url:
http://www.zetetic.net/blog/2010/06/11/introducing-rack-campaign?utm_campaign=rack-campaign&utm_source=blog&utm_medium=internets&utm_content=example%20link
The former is much better than the latter, especially for newsletters and other promotional links. And with a Rack application and a YAML file you can host it yourself, you don’t need to rely on bit.ly or other URL shorteners, and you can “fix” any mistakes after publishing a URL simply by updating the YAML file and reloading Unicorn (taking advantage of zero down-time!) [ You could use another Rack-server, we like Unicorn. ]
Installation
gem install rack-campaign
The rest depends on how you intend to use it.
Example Files
In the /examples
directory of the source distribution are some sample configuration files. config.ru
is a rackup
file, initializing the rack-campaign middleware. You don’t have to use rack-campaign as a stand-alone Rack application, you could instead use it in a middleware stack (although you might want to modify it’s behavior). You probably want to use the map directive in that case to assign rack-campaign to a particular url path (we use /c).
Example Configuration
This is how we use rack-campaign as a stand-alone Rack application. Nginx is our web-server, and we use Unicorn to serve up rack-campaign for the /c path:
/www/campaigns/campaigns.yml:
blog-rack-campaign:
url: http://dev.zetetic.net/blog/2010/06/11/introducing-rack-campaign
tokens:
campaign: rack-campaign
source: blog
medium: internets
content: example link
blog-getstrip:
url: http://getstrip.com
tokens:
campaign: rack-campaign
source: blog
medium: internets
term: strip rocks!
content: example link
/www/campaigns/config.ru:
# Rack-up application config
require 'rubygems'
require 'rack/zetetic/campaign'
run Rack::Zetetic::Campaign.new('/www/campaigns/campaigns.yml')
nginx.conf:
# define upstream for campaign routing
upstream campaigns {
server unix:/www/campaigns/tmp/sockets/unicorn.sock;
}
location /c {
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_max_temp_file_size 0;
# forward everything else to the mongrel cluster
if (!-f $request_filename) {
proxy_pass http://campaigns;
break;
}
}
/etc/init.d/unicorn_rack:
#!/bin/bash
#
# unicorn_rack Startup script for Unicorn master processes
#
# chkconfig: - 85 15
# description: unicorn is a magical process offering up workers to nginx
#
USER=mongrel
RETVAL=0
APPS=( '/www/campaigns' )
for APP in "${APPS[@]}"
do
case "$1" in
start)
echo "Starting up $APP"
cd $APP
sudo -u $USER unicorn -c $APP/unicorn.rb -E production -D
RETVAL=$?
;;
stop)
echo "Stopping $APP"
PID=`ps auxw | grep 'unicorn master' | grep $APP | grep -v grep | awk '{ print $2 }'`
sudo -u $USER kill -INT $PID
RETVAL=$?
;;
restart)
$0 stop
sleep 2
$0 start
;;
reload)
echo "Re-loading $APPS"
PID=`ps auxw | grep 'unicorn master' | grep $APP | grep -v grep | awk '{ print $2 }'`
sudo -u $USER kill -HUP $PID
RETVAL=$?
;;
*)
echo "Usage: unicorn_rack {start|stop|restart|reload}"
exit 1
;;
esac
done
exit $RETVAL