Leevi Graham — Wednesday 17th September, 9:22pm
Using URL rewrites to make ExpressionEngine, Campaign Monitor & Google Analytics play nice
After our appearance at the Rapid Solutions conference, we got to work chasing up the leads that were generated through our booth and presentation. The first phase of this process was to send all the attendees a nice follow up email thanking them for their support and dropping by the booth.
Campaign Monitor + Google Analytics
We always use CampaignMonitor.com and Google Analytics to send and track our email campaigns. They are a reliable and powerful combination providing detailed reports on opening rates, bounce rates and user tracking. I’m not going to go into how to set up Google Analytics in Campaign Monitor, you can find out more about the process here.
To track the users behaviour and communicate with Google, Campaign Monitor automatically adds the necessary query string to outgoing links in your email. Using the following outgoing link as an example:
http://www.abcwidgets.com/email
Campaign Monitor will add the Google tracking code, modifying the link. The new outgoing link will look similar to:
http://abcwidgets.cmail1.com/l/12345/l/www.abcwidgets.com/email?utm_medium=email&↩
utm_source=Campaign+Monitor&utm_content=[email]&utm_campaign=Newcastle+Web+Design+↩
Development+Campaign&utm_term=visit+out+site
When a user clicks on the outgoing link they will be sent to the Campaign Monitor server where the click is recorded and the user is redirected to:
http://www.abcwidgets.com/email?utm_medium=email&utm_source=Campaign+Monitor&↩
utm_content=[email]&utm_campaign=Newcastle+Web+Design+Development+Campaign&↩
utm_term=visit+out+site
This is pretty standard stuff and generally won’t affect how most websites operate. However we recently experienced a couple of issues when using the Google tracking code, ExpressionEngine and the remove index.php URL rewrite technique.
Rewriting ExpressionEngine URLs using .htaccess
Using the standard “include method” remove index.php rewrite rule:
# Remove index.php
# Uses the "include method"
# http://expressionengine.com/wiki/Remove_index.php_From_URLs/#Include_List_Method
RewriteCond %{REQUEST_URI} !(\.[a-zA-Z0-9]{1,5})$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} ^/(member|siteP[0-9]{2,8}) [NC]
RewriteRule ^(.*)$ /index.php?/$1 [L]
the example URL will be rewritten to:
http://www.abcwidgets.com/index.php?/email?utm_medium=email&utm_source=Campaign+Monitor&↩
utm_content=[email]&utm_campaign=Newcastle+Web+Design+Development+Campaign&↩
utm_term=visit+out+site
ExpressionEngine will render the index template in the email template group with the following query string parameters:
utm_campaign Newcastle+Web+Design+Development+Campaign
utm_content [email]
utm_medium email
utm_source Campaign+Monitor
utm_term visit+out+site
Perfect… That’s exactly what is expected, despite the double “?” in the URL (we’ll fix that later).
The site index 404 problem
The problem arrises when the link directs the user to the homepage URL without a template group and template. In this case Campaign Monitor will produce the following URL:
http://www.abcwidgets.com/?utm_medium=email&utm_source=Campaign+Monitor&↩
utm_content=[email]&utm_campaign=Newcastle+Web+Design+Development+Campaign&↩
utm_term=visit+out+site
ExpressionEngine will try and render the utm_medium=email&utm_source=Campaign+Monitor&utm_content=[email]&utm_campaign=Newcastle+Web+Design+Development+Campaign&utm_term=visit+out+site as the template group name which obviously doesn’t exist and the user will be presented with a 404 error.
At this stage I should also note that Campaign Monitor and ExpressionEngine is not doing anything wrong here.
The solution
To avoid the remove index.php rule rewriting the url and rendering a non-existent template we are going to hijack the request and render the index template.
To do this we first test if the request query string starts with utm_medium using:
RewriteCond %{QUERY_STRING} ^utm_medium
Then check if there is nothing in the request uri:
RewriteCond %{REQUEST_URI} ^/$ [NC]
Finally if the two conditions are met, the url is rewritten using the correct template and template group with the query string appended to the end of the URL. In the example below site is the template group and index is the template. The [L] flag tells apache to stop processing the .htaccess rules.
RewriteRule (.*) /index.php?/site/index/&%{QUERY_STRING} [L]
The full .htaccess rewrite rule that first handles the homepage rewrite and then URLs with template groups and templates is:
# rewrite homepage urls that have the google query string
RewriteCond %{QUERY_STRING} ^utm_medium
RewriteCond %{REQUEST_URI} ^/$ [NC]
RewriteRule (.*) /index.php?/site/index/&%{QUERY_STRING} [L]
# Remove index.php
# Uses the "include method"
# http://expressionengine.com/wiki/Remove_index.php_From_URLs/#Include_List_Method
RewriteCond %{REQUEST_URI} !(\.[a-zA-Z0-9]{1,5})$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} ^/(member|siteP[0-9]{2,8}) [NC]
RewriteRule ^(.*)$ /index.php?$1 [L]
One final touch
One final touch is to make sure any Google tracking code is properly attached to urls that have existing templates and template groups. A slight modification to the last line of the remove index.php rule provides the fix. We’ll simply use an ‘&’ character to join the existing template group/template query with the Google tracking code. After the modification the new line is:
RewriteRule ^(.*)$ /index.php?$1&%{QUERY_STRING} [L]
Using the example url earlier in this post, our modified rewrite will produce:
http://www.abcwidgets.com/index.php?/email&utm_medium=email&↩
utm_source=Campaign+Monitor&utm_content=[email]&↩
utm_campaign=Newcastle+Web+Design+Development+Campaign&utm_term=visit+out+site
The final .htaccess rules
The final .htaccess rules, including turning on the rewrite engine and settings the rewrite base looks like:
# Turn the rewrite engine on
RewriteEngine On
# Set the rewrite base
RewriteBase /
# Rewrite homepage urls that have the google query string
RewriteCond %{QUERY_STRING} ^utm_medium
RewriteCond %{REQUEST_URI} ^/$ [NC]
RewriteRule (.*) /index.php?/site/index/&%{QUERY_STRING} [L]
# Remove index.php
# Uses the "include method"
# http://expressionengine.com/wiki/Remove_index.php_From_URLs/#Include_List_Method
RewriteCond %{REQUEST_URI} !(\.[a-zA-Z0-9]{1,5})$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} ^/(member|siteP[0-9]{2,8}) [NC]
RewriteRule (.*) /index.php?/site/index/&%{QUERY_STRING}
The conclusion
So there you have it — how to combine Campaign Monitor’s Google tracking code and ExpressionEngine URL rewriting.
Caveats
This solution works on our setup but it may not work on yours. Post a comment if you have any trouble applying the code above and I’ll try and help out.





Comments
The following 13 people were compelled to have their say. We encourage you to do the same.
kevin said on Thursday 26th February, 10:42am: 1
HI Leevi, iam having a similar issue maybe you can help me out with. Im using your LG .htaccess Generator to create the htaccess and removine index.php. our internet marketing team is running a campaign and in the campaign are links to our sites homepage with a appended source code. The appended source code they are using is /?source=prwebfeb09/. but when the user clicks on the links and it takes them to http://www.rezstream.com/?source=prwebfeb09/ it is giving a 404 because there is no template named ?source=prwebfeb09/
thanks for your help
kevin said on Friday 27th February, 12:50am: 2
here is a link to the EE forum thread
http://expressionengine.com/forums/viewthread/106983/#538526
Ian Pitts said on Thursday 28th May, 6:42am: 3
Thank you SO much Leevi! This got me most of the way there, but I’m having specific issues with how Campaign Monitor is converting a site link’s http:// portion into http:// and I believe EE is choking on it for security reasons.
Is there a way to just rewrite that out within .htaccess?
Merv said on Friday 19th June, 10:19pm: 4
Due to limitations imposed by the hosting company I have removed everthing except the rewrite section from the .htaccess generator (because they only allow the rewrite nothing else). Its doing its job now but as soon as I remove index.php from the settings I loose the formating to the page… for some reason its not using the css files, however the url appears perfect without index.php in it. Please can you point me in the right direction. Any help appreciated thank you.
Adam George said on Friday 26th June, 4:03pm: 5
I just ran into this issue and found your article helpful, thank you. A couple of things though…
“The final .htaccess rules, including turning on the rewrite engine and settings the rewrite base looks like:”
(Need to remove ‘s’ from ‘settings’)
In the ‘final’ .htaccess rule, the last line is:
RewriteRule (.*) /index.php?/site/index/&%{QUERY_STRING}
However, I think perhaps this is wrong, as it would cause all urls to use ‘/site/index’… correct me if I’m wrong. It maybe should be:
RewriteRule ^(.*)$ /index.php?$1&%{QUERY_STRING} [L]
This rule throws a server error for me (probably just my setup):
RewriteRule ^(.*)$ /index.php?$1&%{QUERY_STRING} [L]
Brandon Richards said on Wednesday 14th October, 3:43am: 6
@Adam the rule he is referencing is only for links that
1st contain a query term for ^utm_medium
2nd the link is the base url, e.g. http://www.example.com/
3rd if all of are true it then rewrites the home page url to include the EE template group and index template so that EE knows what page is being requested.
The additional rules are for everything else.
Thanks Leevi! saved me a headache
Andy Johnson said on Sunday 8th November, 1:44pm: 7
Thanks so much for taking the time to post this information Leevi.
One question, if I wanted to rewrite homepage URLs that had ANY query string (not just ones that start with “utm_medium”), could it just be written like this:
# Rewrite homepage urls that have the any query strings
RewriteCond %{QUERY_STRING} ^
RewriteCond %{REQUEST_URI} ^/$ [NC]
RewriteRule (.*) /index.php?/site/index/&%{QUERY_STRING} [L]
Seems like this would work, but not sure if this is the proper way to do it. Any thoughts? Thanks!
mahalie said on Wednesday 10th February, 11:24am: 8
Thanks MUCH for the code and your clear explanation. I just used this for a MailChimp campaign - works like a charm…
Christopher Robert Kennedy said on Sunday 9th May, 1:09am: 9
Hi Leevi,
Thanks for all you’ve done with this software. It’s a real lifesaver. I’ve got an issue with my current setup, and getting the system queries going properly. I have index.php being rewritten as “in/houston” (long story, they really want that addition), and ultimately, it works just fine, on the front end. However, I am running into that issue on the backside when trying to perform user registrations. Simply put, they’re not happening, and I’m sure it’s because I’ve got this “double directory” structure. In any case, my rewrite code is like the following:
RewriteCond %{QUERY_STRING} ^utm_medium
RewriteCond %{REQUEST_URI} ^/$ [NC]
RewriteRule (.*) /index.php?/page_templates/index/&%{QUERY_STRING} [L]
and the homepage default is /page_templates/index.
Is there anything I could be forgetting in this example?
Thanks again!
Greg said on Saturday 31st July, 2:24pm: 10
hmm very useful, thankyou for this, will definatley being using this later on
Eugene said on Saturday 27th November, 1:23am: 11
Hi Levi! Great solution, doesn’t work for EE2 though :( Is there any way to get rid of index.php in the urls and solve problem with Google Analytics at the same time in ExpressionEngine 2.1.1?
Thankx for help!
Daniel Boswell said on Wednesday 13th July, 12:07pm: 12
@mahalie would you mind explaining how you used the rewrite tutorial above with MailChimp? I’m trying to figure out how to set up a webhook from MC to EE and I’m hoping you may have already done something similar that can point me in the right direction.
Anyone else who has experience with MailChimp please also share how this might work.
Outside Design said on Wednesday 7th September, 8:46pm: 13
Hi Leevi
Many. many thanks for the examples - hit this issue with Campaign Monitor, MailChimp and our own in-house CMS. Have updated our .htaccess code and am currently testing.
I was wondering about all the Russian posts so popped the text into an online translator - looks like they’re all bits of ads to generate back-links.
Your comment
Please keep your comments friendly and on topic.