Services Newcastle’s most advanced web company. Learn more ›

Photo of Leevi Graham

Leevi GrahamCode Monkey

Newism Pty Ltd
Newcastle, NSW Australia

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.

  1. kevin's Gravatar

    kevin said on Thursday 26th February, 10:42am:

    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

  2. kevin's Gravatar

    kevin said on Friday 27th February, 12:50am:

    here is a link to the EE forum thread
    http://expressionengine.com/forums/viewthread/106983/#538526

  3. Ian Pitts's Gravatar

    Ian Pitts said on Thursday 28th May, 6:42am:

    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?

  4. Merv's Gravatar

    Merv said on Friday 19th June, 10:19pm:

    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.

  5. Adam George's Gravatar

    Adam George said on Friday 26th June, 4:03pm:

    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]

  6. Brandon Richards's Gravatar

    Brandon Richards said on Wednesday 14th October, 3:43am:

    @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

  7. Andy Johnson's Gravatar

    Andy Johnson said on Sunday 8th November, 1:44pm:

    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!

  8. mahalie's Gravatar

    mahalie said on Wednesday 10th February, 11:24am:

    Thanks MUCH for the code and your clear explanation. I just used this for a MailChimp campaign - works like a charm…

  9. Christopher Robert Kennedy's Gravatar

    Christopher Robert Kennedy said on Sunday 9th May, 1:09am:

    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!

  10. Greg's Gravatar

    Greg said on Saturday 31st July, 2:24pm:

    hmm very useful, thankyou for this, will definatley being using this later on

  11. Eugene's Gravatar

    Eugene said on Saturday 27th November, 1:23am:

    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!

  12. Daniel Boswell's Gravatar

    Daniel Boswell said on Wednesday 13th July, 12:07pm:

    @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.

  13. Outside Design's Gravatar

    Outside Design said on Wednesday 7th September, 8:46pm:

    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.