Skip to content

Instantly share code, notes, and snippets.

@iconifyit
Last active February 10, 2023 03:09
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save iconifyit/c8d715d62b6e3960696ac1c9cbd231c5 to your computer and use it in GitHub Desktop.
Save iconifyit/c8d715d62b6e3960696ac1c9cbd231c5 to your computer and use it in GitHub Desktop.
A/B Testing with htaccess
# ############################### #
# A/B TESTING (START) #
# ############################### #
# (1) Check if our cookie is already set.
# If so, redirect to the previously-viewed page.
RewriteCond %{HTTP_COOKIE} ab_test_vers=([^;]+)
RewriteRule ^THE-PAGE-BEING-TESTED$ HTTP://YOUR-DOMAIN.COM/tracking/%1 [cookie=ab_test_vers_match:true:YOUR-DOMAIN.COM,L]
# (2) If no cookie is set (new visitor)
# AND the current time is on an even-numbered second
# Rewrite to /test-option-a AND set our cookie to `even`
RewriteCond %{HTTP_COOKIE} !ab_test_vers=([^;]+)
RewriteCond %{TIME_SEC} [02468]$
RewriteRule ^test-page$ /tracking/even [cookie=ab_test_vers:even:YOUR-DOMAIN.COM,L]
Redirect 302 /tracking/even HTTP://YOUR-DOMAIN.COM/a/test-page
# (3) If no cookie is set (new visitor)
# AND the current time is on an odd-numbered second
# Rewrite to /test-option-b AND set our cookie to `odd`
RewriteCond %{HTTP_COOKIE} !ab_test_vers=([^;]+)
RewriteCond %{TIME_SEC} [13579]$
RewriteRule ^test-page$ /tracking/odd [cookie=ab_test_vers:odd:YOUR-DOMAIN.COM,L]
Redirect 302 /tracking/odd HTTP://YOUR-DOMAIN.COM/b/test-page
# ############################### #
# A/B TESTING (END) #
# ############################### #
@iconifyit
Copy link
Author

iconifyit commented Jul 19, 2019

I think the code below is what you need. The only caveat is that all of your test pages have to begin with "test-page", so "test-page-1", "test-page-2", etc. You can change this by replacing every instance of "test-page" with whatever prefix you want. Be sure to clear your cookies before testing the rules below.

# ############################### #
#        A/B TESTING (START)      #
# ############################### #

# (1) Check if our cookie is already set.
#     If so, redirect to the previously-viewed page.

RewriteCond %{HTTP_COOKIE} ab_test_vers=([^;]+)
RewriteRule ^(test-page.*)/?$ HTTPS://YOUR-DOMAIN-COM/tracking/%1/$1 [cookie=ab_test_vers_match:true:YOUR-DOMAIN-COM,L]

# (2) If no cookie is set (new visitor)
#     AND the current time is on an even-numbered second
#     Rewrite to /test-option-a AND set our cookie

RewriteCond   %{HTTP_COOKIE} !ab_test_vers=([^;]+)
RewriteCond   %{TIME_SEC} [02468]$
RewriteRule   ^(test-page.*/?)$ /tracking/even/$1 [cookie=ab_test_vers:even:YOUR-DOMAIN-COM,L]
RedirectMatch 302 ^/tracking/even/(.*/?)$ HTTPS://YOUR-DOMAIN-COM/a/$1

# (3) If no cookie is set (new visitor)
#     AND the current time is on an odd-numbered second
#     Rewrite to /test-option-a AND set our cookie

RewriteCond   %{HTTP_COOKIE} !ab_test_vers=([^;]+)
RewriteCond   %{TIME_SEC} [13579]$
RewriteRule   ^(test-page.*/?)$ /tracking/odd/$1 [cookie=ab_test_vers:odd:YOUR-DOMAIN-COM,L]
RedirectMatch 302 ^/tracking/odd/(.*/?)$ HTTPS://YOUR-DOMAIN-COM/b/$1

# ############################### #
#        A/B TESTING (END)        #
# ############################### #

@iconifyit
Copy link
Author

iconifyit commented Jul 19, 2019

@birender The rules below will probably be easier to manage. They test the entire site (if you want). You will need to create 3 sub-pages on your site: @, a, b so you'll end up with :

https://yourdomain.com/@/test-page-1
https://yourdomain.com/a/test-page-1
https://yourdomain.com/b/test-page-1

The flow will be that a user comes to https://yourdomain.com/@/some-page and be redirected to either https://yourdomain.com/a/some-page or https://yourdomain.com/b/some-page

So any link you use that starts with /@/any-page will be redirected to the same page name under /a/ or /b/ depending on the timestamp on their first visit.

# ############################### #
#        A/B TESTING (START)      #
# ############################### #

# (1) Check if our cookie is already set.
#     If so, redirect to the previously-viewed page.

RewriteCond %{HTTP_COOKIE} ab_test_vers=([^;]+)
RewriteRule ^@(.*)/?$ HTTPS://YOUR-DOMAIN-COM/tracking/%1/$1 [cookie=ab_test_vers_match:true:YOUR-DOMAIN-COM,L]

# (2) If no cookie is set (new visitor)
#     AND the current time is on an even-numbered second
#     Rewrite to /test-option-a AND set our cookie

RewriteCond   %{HTTP_COOKIE} !ab_test_vers=([^;]+)
RewriteCond   %{TIME_SEC} [02468]$
RewriteRule   ^@/(.*)/?$ /tracking/even/$1 [cookie=ab_test_vers:even:YOUR-DOMAIN-COM,L]
RedirectMatch 302 ^/tracking/even/(.*/?)$ HTTPS://YOUR-DOMAIN-COM/a/$1

# (3) If no cookie is set (new visitor)
#     AND the current time is on an odd-numbered second
#     Rewrite to /test-option-a AND set our cookie

RewriteCond   %{HTTP_COOKIE} !ab_test_vers=([^;]+)
RewriteCond   %{TIME_SEC} [13579]$
RewriteRule   ^@/(.*)/?$ /tracking/odd/$1 [cookie=ab_test_vers:odd:YOUR-DOMAIN-COM,L]
RedirectMatch 302 ^/tracking/odd/(.*/?)$ HTTPS://YOUR-DOMAIN-COM/b/$1

# ############################### #
#        A/B TESTING (END)        #
# ############################### #

@iconifyit
Copy link
Author

@birender I have created another gist with the whole-site version which you can find here : https://gist.github.com/iconifyit/1b5c51c142f2c929c27c953ae85a0f00

@ALPJeff
Copy link

ALPJeff commented Oct 16, 2019

Scott,

First, THANK YOU so much for sharing this, it's exactly what we were looking for & your very thorough explanation of everything was a huge help.

Next, I do have a question - do you have any insight on why this rule would cause JS issues on a website? We muddled through modifying the rule for homepage a/b testing like you see here & it wrecked some core eCommerce functions on our site, most likely my own fault:

# ############################### #
#        A/B TESTING (START)      #
# ############################### #

# (1) Check if our cookie is already set.
#     If so, redirect to the previously-viewed page.

RewriteCond %{HTTP_COOKIE} ab_test_vers=([^;]+)
RewriteRule ^$ /tracking/%1 [cookie=ab_test_vers_match:true:example.com,L]


# (2) If no cookie is set (new visitor)
#     AND the current time is on an even-numbered second
#     Rewrite to /test-option-a AND set our cookie

RewriteCond %{HTTP_COOKIE} !ab_test_vers=([^;]+)
RewriteCond %{TIME_SEC} [02468]$
RewriteRule ^$ /tracking/even [cookie=ab_test_vers:even:example.com,L]
Redirect 302 /tracking/even https://example.com/welcome/

# (3) If no cookie is set (new visitor)
#     AND the current time is on an odd-numbered second
#     Rewrite to /test-option-a AND set our cookie

RewriteCond %{HTTP_COOKIE} !ab_test_vers=([^;]+)
RewriteCond %{TIME_SEC} [13579]$
RewriteRule ^$ /tracking/odd [cookie=ab_test_vers:odd:example.com,L]
Redirect 302 /tracking/odd https://example.com/start-here/

# ############################### #
#        A/B TESTING (END)        #
# ############################### #

@iconifyit
Copy link
Author

Hey Jeff. That makes me happy to hear. I'm glad someone else finds it useful. I don't know off the top of my head why it would break your JS but it may have to do with the rewrite/redirect. I would be happy to take a quick look at the code if you want to email it to me at scott_at_atomiclotus_dot_net.

@birender
Copy link

birender commented Oct 18, 2019 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment