Skip to content

Commit

Permalink
Configure Google Analytics dimension for A/B test
Browse files Browse the repository at this point in the history
Make the dimension a required parameter when configuring a test, because
we expect every A/B test to report its results to Google Analytics.

Include the dimension in the `meta` tag, so that the GA JavaScript will
report the user's variant using the correct GA dimension.
  • Loading branch information
suzannehamilton committed Feb 10, 2017
1 parent fd4569f commit c612377
Show file tree
Hide file tree
Showing 6 changed files with 38 additions and 14 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ that you pass to the Gem. The cookie name is case-sensitive.
To enable testing in the app, your Rails app needs:

1. Some piece of logic to be A/B tested
2. A HTML meta tag that will be used to measure the results
2. A HTML meta tag that will be used to measure the results, and which specifies
the dimension to use in Google Analytics
3. A response HTTP header that tells Fastly you're doing an A/B test

Let's say you have this controller:
Expand All @@ -38,7 +39,7 @@ Let's say you have this controller:
# app/controllers/party_controller.rb
class PartyController < ApplicationController
def show
ab_test = GovukAbTesting::AbTest.new("your_ab_test_name")
ab_test = GovukAbTesting::AbTest.new("your_ab_test_name", dimension: 300)
@requested_variant = ab_test.requested_variant(request)
@requested_variant.configure_response(response)

Expand Down
8 changes: 6 additions & 2 deletions lib/govuk_ab_testing/ab_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,18 @@ module GovukAbTesting
class AbTest
attr_reader :ab_test_name

def initialize(ab_test_name)
# @param request [String] the name of the A/B test
# @param dimension [Integer] the dimension registered with Google Analytics
# for this specific A/B test
def initialize(ab_test_name, dimension:)
@ab_test_name = ab_test_name
@dimension = dimension
end

# @param request [ApplicationController::Request] the `request` in the
# controller.
def requested_variant(request)
RequestedVariant.new(self, request)
RequestedVariant.new(self, request, @dimension)
end

# Internal name of the header
Expand Down
9 changes: 6 additions & 3 deletions lib/govuk_ab_testing/minitest_helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module MinitestHelpers
def with_variant(args)
ab_test_name, variant = args.first

ab_test = GovukAbTesting::AbTest.new(ab_test_name.to_s)
ab_test = GovukAbTesting::AbTest.new(ab_test_name.to_s, dimension: args[:dimension])

@request.headers[ab_test.request_header] = variant
requested_variant = ab_test.requested_variant(@request)
Expand All @@ -13,8 +13,11 @@ def with_variant(args)
assert_equal ab_test.response_header, response.headers['Vary'], "You probably forgot to use `configure_response`"

unless args[:assert_meta_tag] == false
raise "Cannot test the A/B meta tag because no expected :dimension parameter was specified by test" unless args[:dimension]

assert_meta_tag "govuk:ab-test",
ab_test.meta_tag_name + ':' + requested_variant.variant_name,
args[:dimension],
"You probably forgot to add the `analytics_meta_tag`"
end
end
Expand All @@ -34,8 +37,8 @@ def assert_unaffected_by_ab_test

private

def assert_meta_tag(name, content, message)
assert_select "meta[name='#{name}'][content='#{content}']", 1, message
def assert_meta_tag(name, content, dimension, message)
assert_select "meta[name='#{name}'][content='#{content}'][data-analytics-dimension='#{dimension}']", 1, message
end
end
end
9 changes: 7 additions & 2 deletions lib/govuk_ab_testing/requested_variant.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@ class RequestedVariant
# @param ab_test [AbTest] the A/B test being performed
# @param request [ApplicationController::Request] the `request` in the
# controller.
def initialize(ab_test, request)
# @param dimension [Integer] the dimension registered with Google Analytics
# for this specific A/B test
def initialize(ab_test, request, dimension)
@ab_test = ab_test
@request = request
@dimension = dimension
end

# Get the bucket this user is in
Expand Down Expand Up @@ -39,7 +42,9 @@ def configure_response(response)
#
# @return [String]
def analytics_meta_tag
'<meta name="govuk:ab-test" content="' + ab_test.meta_tag_name + ':' + variant_name + '">'
'<meta name="govuk:ab-test" ' +
'content="' + ab_test.meta_tag_name + ':' + variant_name + '" ' +
'data-analytics-dimension="' + @dimension.to_s + '">'
end
end
end
11 changes: 10 additions & 1 deletion spec/minitest_helpers_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,23 @@ class AnExampleMiniTestCase < FakeMinitestControllerTestCase
include GovukAbTesting::MinitestHelpers

def test_name_of_a_test
with_variant(example: 'B') do
with_variant(example: 'B', dimension: 50) do
# We're testing the behaviour of `with_variant` here.
end
end

def test_with_missing_dimension
with_variant(example: 'B') do
end
end
end

describe GovukAbTesting::MinitestHelpers do
it "runs without errors" do
AnExampleMiniTestCase.new.test_name_of_a_test
end

it "rejects test with missing dimension parameter" do
expect { AnExampleMiniTestCase.new.test_with_missing_dimension }.to raise_error(/dimension/)
end
end
10 changes: 6 additions & 4 deletions spec/requested_variant_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

RSpec.describe GovukAbTesting::RequestedVariant do
def ab_test
GovukAbTesting::AbTest.new("EducationNav")
GovukAbTesting::AbTest.new("EducationNav", dimension: 500)
end

describe '#variant_name' do
Expand Down Expand Up @@ -38,12 +38,14 @@ def ab_test
end

describe '#analytics_meta_tag' do
it "returns the tag" do
it "returns the tag with the analytics dimension" do
activesupport_request = double(headers: { 'HTTP_GOVUK_ABTEST_EDUCATIONNAV' => 'A'})

requested_variant = ab_test.requested_variant(activesupport_request)
requested_variant = GovukAbTesting::AbTest.new("EducationNav", dimension: 207).
requested_variant(activesupport_request)

expect(requested_variant.analytics_meta_tag).to eql("<meta name=\"govuk:ab-test\" content=\"EducationNav:A\">")
expect(requested_variant.analytics_meta_tag).to eql(
"<meta name=\"govuk:ab-test\" content=\"EducationNav:A\" data-analytics-dimension=\"207\">")
end
end

Expand Down

0 comments on commit c612377

Please sign in to comment.