visitor_sources 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md ADDED
@@ -0,0 +1,11 @@
1
+ Visitor Sources
2
+ ===============
3
+
4
+ This code is not finished
5
+ -------------------------
6
+
7
+ Track where a visitor has come from and kep a record of each visit in the cookie. To get around the "last click wins" nature of Google Analytics
8
+
9
+
10
+ # requires the use of Rack::Session::Cookie 
11
+
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.0
@@ -0,0 +1,59 @@
1
+ class SearchEngine
2
+ SEARCH_ENGINES = {
3
+ "google" => "q",
4
+ "yahoo" => "p",
5
+ "msn" => "q",
6
+ "aol" => "query",
7
+ "aol" => "encquery",
8
+ "lycos" => "query",
9
+ "ask" => "q",
10
+ "altavista" => "q",
11
+ "netscape" => "query",
12
+ "cnn" => "query",
13
+ "looksmart" => "qt",
14
+ "about" => "terms",
15
+ "mamma" => "query",
16
+ "alltheweb" => "q",
17
+ "gigablast" => "q",
18
+ "voila" => "rdata",
19
+ "virgilio" => "qs",
20
+ "live" => "q",
21
+ "baidu" => "wd",
22
+ "alice" => "qs",
23
+ "yandex" => "text",
24
+ "najdi" => "q",
25
+ "aol" => "q",
26
+ "club-internet" => "query",
27
+ "mama" => "query",
28
+ "seznam" => "q",
29
+ "search" => "q",
30
+ "wp" => "szukaj",
31
+ "onet" => "qt",
32
+ "netsprint" => "q",
33
+ "google.interia" => "q",
34
+ "szukacz" => "q",
35
+ "yam" => "k",
36
+ "pchome" => "q",
37
+ "kvasir" => "searchExpr",
38
+ "sesam" => "q",
39
+ "ozu" => "q",
40
+ "terra" => "query",
41
+ "nostrum" => "query",
42
+ "mynet" => "q",
43
+ "ekolay" => "q",
44
+ "search.ilse" => "search_for"}
45
+
46
+ attr_accessor :name, :search_parameter
47
+
48
+ def self.find(domain)
49
+ SEARCH_ENGINES.each do |name, search_parameter|
50
+ if domain =~ /#{name}/
51
+ engine = SearchEngine.new
52
+ engine.name = name
53
+ engine.search_parameter = search_parameter
54
+ return engine
55
+ end
56
+ end
57
+ return nil
58
+ end
59
+ end
@@ -0,0 +1,109 @@
1
+ # To minimise amount of stored data in the cookie (limited to 4KB) a traffic source gets converted to a string with variables
2
+ # seperated by a pipe(|), different traffic sources are separated by commas(,)
3
+ #
4
+ # The string looks like the following:
5
+ # 1|1266945604|ppc|just%20tv%20stands|google|December%20Campaign|/content
6
+ # Broken down, this is what the variables mean
7
+ # 1 => encoder_version makes it easy to change how this works in the future without loosing old data already in peoples cookies
8
+ # 1266945604 => unix_timestamp at which the TrafficSource was generated
9
+ # ppc => medium how the person cameto the site (main ones are cpc, direct, organic or referal)
10
+ # just%20tv%20stands => term The search term that bought the user to the site [not required]
11
+ # google => source Where the person came from. Could be keyword such as `google` or a domain name [not required]
12
+ # December%20Campaign => campaign Usually set for ppc traffic in adwords [not required]
13
+ # /content => content when a referal, this is the path from which they came from [not required]
14
+
15
+ require "uri"
16
+ class TrafficSource
17
+ attr_accessor :encoder_version, :unix_timestamp, :medium, :term, :source, :campaign, :content, :custom_parameter_mapping, :env
18
+
19
+ COOKIE_LINE_PARAMETERS = ['encoder_version', 'unix_timestamp', 'medium', 'term', 'source', 'campaign', 'content']
20
+ STANDARD_PARAMETER_MAPPING = {:medium => :utm_medium, :term => :utm_term, :source => :utm_source, :campaign => :utm_campaign, :content => :utm_content}
21
+
22
+ def initialize(attributes={})
23
+ attributes.each do |key, value|
24
+ self.send("#{key}=", value)
25
+ end
26
+ end
27
+
28
+ def self.updated_rack_environment(old_env, custom_parameter_mapping = {})
29
+ old_env["rack.session"][:traffic_sources] ||= ''
30
+ traffic_sources = TrafficSources.new(old_env["rack.session"][:traffic_sources])
31
+ latest_source = TrafficSource.initialize_with_rack_env(old_env, custom_parameter_mapping)
32
+ return old_env if latest_source.to_s.nil?
33
+ if traffic_sources.length > 0
34
+ return old_env if latest_source.same_as?(traffic_sources.last)
35
+ end
36
+ traffic_sources << latest_source
37
+ old_env["rack.session"][:traffic_sources] = traffic_sources.to_s
38
+ return old_env
39
+ end
40
+
41
+ def TrafficSource.initialize_with_rack_env(env, custom_parameter_mapping = {})
42
+ traffic_source = self.new(:env => env, :custom_parameter_mapping => custom_parameter_mapping,
43
+ :unix_timestamp => Time.now.to_i, :encoder_version => 1)
44
+
45
+ COOKIE_LINE_PARAMETERS.last(5).each do |attribute|
46
+ traffic_source.send("#{attribute}=", traffic_source.query_string_value_for(attribute.to_sym))
47
+ end
48
+
49
+ #special case for adwords auto tagging
50
+ traffic_source.medium = 'cpc' if traffic_source.medium.nil? && !traffic_source.env["rack.request.query_hash"]["gclid"].nil?
51
+
52
+ if traffic_source.medium.nil?
53
+ if env["HTTP_REFERER"].nil?
54
+ traffic_source.medium = "direct"
55
+ else
56
+ traffic_source.medium = "referal" unless env["HTTP_REFERER"] =~ /#{env['HTTP_HOST']}/
57
+ end
58
+ end
59
+ if traffic_source.source.nil?
60
+ begin
61
+ uri = URI.parse(env["HTTP_REFERER"])
62
+ traffic_source.source = uri.host
63
+ search_engine = SearchEngine.find(traffic_source.source)
64
+ if search_engine
65
+ traffic_source.source = search_engine.name
66
+ traffic_source.term = Rack::Utils.parse_query(uri.query)[search_engine.search_parameter] if traffic_source.term.nil?
67
+ traffic_source.medium = "organic" unless traffic_source.medium == 'cpc'
68
+ end
69
+ traffic_source.content = uri.path if traffic_source.content.nil? && !search_engine
70
+ rescue; end
71
+ end
72
+ return traffic_source
73
+ end
74
+
75
+ def TrafficSource.initialize_from_string(string)
76
+ string_attributes = string.split("|")
77
+ traffic_source = TrafficSource.new(:encoder_version => string_attributes[0].to_i, :unix_timestamp => string_attributes[1].to_i)
78
+ COOKIE_LINE_PARAMETERS.last(5).each_with_index do |attribute, index|
79
+ traffic_source.send("#{attribute}=", string_attributes[index+2])
80
+ end
81
+ return traffic_source
82
+ end
83
+
84
+ def to_s
85
+ return nil if medium.nil?
86
+ # join each element by pipes(|), remove any unnecessary unused pipes from the end
87
+ COOKIE_LINE_PARAMETERS.collect{|param| self.send(param)}.join("|").gsub(/\|+$/, '')
88
+ end
89
+
90
+ def query_string_value_for(attribute)
91
+ if custom_parameter_mapping[attribute] && !env["rack.request.query_hash"][custom_parameter_mapping[attribute].to_s].nil?
92
+ return env["rack.request.query_hash"][custom_parameter_mapping[attribute].to_s]
93
+ end
94
+ if env["rack.request.query_hash"][STANDARD_PARAMETER_MAPPING[attribute].to_s]
95
+ return env["rack.request.query_hash"][STANDARD_PARAMETER_MAPPING[attribute].to_s]
96
+ end
97
+ end
98
+
99
+ def same_as?(traffic_source)
100
+ COOKIE_LINE_PARAMETERS.last(5).each do |attribute|
101
+ return false if self.send(attribute).to_s != traffic_source.send(attribute).to_s
102
+ end
103
+ return true
104
+ end
105
+
106
+ def date
107
+ Time.at(unix_timestamp)
108
+ end
109
+ end
@@ -0,0 +1,16 @@
1
+ class TrafficSourceMiddleware
2
+ def initialize(app, options={})
3
+ @app = app
4
+ @options = options
5
+ end
6
+
7
+ def call(env)
8
+ @options[:custom_parameter_mapping] ||= {}
9
+ env["rack.request.query_hash"] = Rack::Utils.parse_query(env["QUERY_STRING"])
10
+ env = TrafficSource.updated_rack_environment(env, @options[:custom_parameter_mapping])
11
+ env[:traffic_sources] = TrafficSources.new(env["rack.session"][:traffic_sources])
12
+ @status, @headers, @response = @app.call(env)
13
+ [@status, @headers, @response]
14
+ end
15
+
16
+ end
@@ -0,0 +1,13 @@
1
+ class TrafficSources < Array
2
+
3
+ def initialize(string)
4
+ traffic_source_strings = string.split(",")
5
+ traffic_source_strings.each do |string|
6
+ self << TrafficSource.initialize_from_string(string)
7
+ end
8
+ end
9
+
10
+ def to_s
11
+ each.collect(&:to_s).join(",")
12
+ end
13
+ end
@@ -0,0 +1,4 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/visitor_sources/search_engine')
2
+ require File.expand_path(File.dirname(__FILE__) + '/visitor_sources/traffic_source')
3
+ require File.expand_path(File.dirname(__FILE__) + '/visitor_sources/traffic_sources')
4
+ require File.expand_path(File.dirname(__FILE__) + '/visitor_sources/traffic_source_middleware')
data/test/app.rb ADDED
@@ -0,0 +1,13 @@
1
+ require 'rubygems'
2
+ require 'sinatra'
3
+ require File.expand_path(File.dirname(__FILE__) + '/../lib/visitor_sources')
4
+
5
+ use Rack::Session::Cookie
6
+ use TrafficSourceMiddleware, :custom_parameter_mapping => {:campaign => :campaign}
7
+
8
+
9
+
10
+ get "/" do
11
+ request.env[:traffic_sources].to_s
12
+ end
13
+
@@ -0,0 +1,18 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/test_helper')
2
+
3
+ class SearchEngineTest < Test::Unit::TestCase
4
+ context "SearchEngineTest" do
5
+ context "find" do
6
+ should "return a search engine if one matches" do
7
+ engine = SearchEngine.find("www.google.com")
8
+ assert_equal "google", engine.name
9
+ assert_equal "q", engine.search_parameter
10
+ end
11
+
12
+ should "return nil if no engine found" do
13
+ engine = SearchEngine.find("www.fakeengine.com")
14
+ assert_nil engine
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,47 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'rack/test'
4
+ require 'shoulda'
5
+ require 'base64'
6
+ require File.expand_path(File.dirname(__FILE__) + '/app')
7
+
8
+ EXAMPLE_RACK_ENV = {
9
+ "rack.session"=>{:traffic_sources=>""},
10
+ "HTTP_HOST"=>"localhost:9393",
11
+ "HTTP_ACCEPT"=>"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
12
+ "SERVER_NAME"=>"localhost",
13
+ "rack.request.cookie_hash"=>{"rack.session"=>"BAh7BjoUdHJhZmZpY19zb3VyY2VzIghBQkM=\n"},
14
+ "rack.url_scheme"=>"http",
15
+ "REQUEST_PATH"=>"/",
16
+ "HTTP_USER_AGENT"=>"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6",
17
+ "HTTP_KEEP_ALIVE"=>"115",
18
+ "rack.errors"=>{},
19
+ "HTTP_ACCEPT_LANGUAGE"=>"en-us,en;q=0.5",
20
+ "SERVER_PROTOCOL"=>"HTTP/1.1",
21
+ "rack.version"=>[1, 0],
22
+ "rack.run_once"=>false,
23
+ "SERVER_SOFTWARE"=>"Mongrel 1.1.5",
24
+ "PATH_INFO"=>"/",
25
+ "REMOTE_ADDR"=>"::1",
26
+ "rack.request.cookie_string"=>"rack.session=BAh7BjoUdHJhZmZpY19zb3VyY2VzIghBQkM%3D%0A",
27
+ "HTTP_REFERER"=>"http://localhost:9393/",
28
+ "SCRIPT_NAME"=>"",
29
+ "rack.multithread"=>true,
30
+ "HTTP_VERSION"=>"HTTP/1.1",
31
+ "HTTP_COOKIE"=>"rack.session=BAh7BjoUdHJhZmZpY19zb3VyY2VzIghBQkM%3D%0A",
32
+ "rack.request.form_vars"=>"",
33
+ "rack.multiprocess"=>false,
34
+ "REQUEST_URI"=>"/",
35
+ "rack.request.form_input"=>{},
36
+ "rack.request.query_hash"=>{},
37
+ "HTTP_ACCEPT_CHARSET"=>"ISO-8859-1,utf-8;q=0.7,*;q=0.7",
38
+ "SERVER_PORT"=>"9393",
39
+ "rack.session.options"=>{:domain=>nil, :expire_after=>nil, :path=>"/"},
40
+ "REQUEST_METHOD"=>"GET",
41
+ "rack.request.form_hash"=>{},
42
+ "rack.request.query_string"=>"",
43
+ "QUERY_STRING"=>"",
44
+ "rack.input"=>{},
45
+ "HTTP_ACCEPT_ENCODING"=>"gzip,deflate",
46
+ "HTTP_CONNECTION"=>"keep-alive",
47
+ "GATEWAY_INTERFACE"=>"CGI/1.2"}
@@ -0,0 +1,22 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/test_helper')
2
+
3
+
4
+ class TrafficSourceMiddlewareTest < Test::Unit::TestCase
5
+ include Rack::Test::Methods
6
+
7
+ def app
8
+ Sinatra::Application
9
+ end
10
+
11
+ def test_should_display_traffic_source_line
12
+ start_time = Time.now.to_i
13
+ get "/", params = {}, rack_env = {}
14
+ assert last_response.ok?
15
+ assert_equal "1|#{start_time}|direct", last_response.body
16
+ sleep 1
17
+ get "/", params = {:campaign => "mycampaign", :utm_medium => "cpc"}, rack_env = {}
18
+ assert_equal "1|#{start_time}|direct,1|#{start_time+1}|cpc|||mycampaign", last_response.body
19
+ end
20
+
21
+ end
22
+
@@ -0,0 +1,214 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/test_helper')
2
+
3
+ # Priority of variables set
4
+ # custom variables configured when using the plugin take the most priority
5
+ # if no custom variable matches, then the standard google variables take priority: 'utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'utm_campaign'
6
+ # if no match standard google variables then try and work out the required data from referers etc
7
+
8
+ class TrafficSourceTest < Test::Unit::TestCase
9
+ context "TrafficSourceTest" do
10
+ setup do
11
+ @rack_env = EXAMPLE_RACK_ENV.dup
12
+ @custom_variable_matches = {:campaign => :custom_campaign, :term => :custom_keywords, :medium => :custom_medium}
13
+ end
14
+ context "initialize_with_rack_env" do
15
+
16
+ context "when there are custom variables in the url present" do
17
+ should "use the custom variables to set the correct TrafficSource" do
18
+ @rack_env["rack.request.query_hash"] = {"custom_campaign" => "MyCamp1", "custom_keywords" => "Product One", "gclid" => "AutoAdwordsTaggingClid"}
19
+ @rack_env["HTTP_REFERER"] = "http://www.google.co.uk/search"
20
+ traffic_source = TrafficSource.initialize_with_rack_env(@rack_env, @custom_variable_matches)
21
+ assert_equal "cpc", traffic_source.medium
22
+ assert_equal "MyCamp1", traffic_source.campaign
23
+ assert_equal "Product One", traffic_source.term
24
+ assert_equal Time.now.to_i, traffic_source.unix_timestamp
25
+ assert_equal "1|#{Time.now.to_i}|cpc|Product One|google|MyCamp1", traffic_source.to_s
26
+ end
27
+
28
+ should "use presume organic if no gclid and from a search engine" do
29
+ @rack_env["rack.request.query_hash"] = {"custom_campaign" => "MyCamp1", "custom_keywords" => "Product One"}
30
+ @rack_env["HTTP_REFERER"] = "http://www.google.co.uk/search"
31
+ traffic_source = TrafficSource.initialize_with_rack_env(@rack_env, @custom_variable_matches)
32
+ assert_equal "organic", traffic_source.medium
33
+ assert_equal "MyCamp1", traffic_source.campaign
34
+ assert_equal "Product One", traffic_source.term
35
+ assert_equal Time.now.to_i, traffic_source.unix_timestamp
36
+ assert_equal "1|#{Time.now.to_i}|organic|Product One|google|MyCamp1", traffic_source.to_s
37
+ end
38
+
39
+ should "assign to cpc if a custom variable says thats the case" do
40
+ @rack_env["rack.request.query_hash"] = {"custom_campaign" => "MyCamp1", "custom_keywords" => "Product One", "custom_medium" => "cpc"}
41
+ @rack_env["HTTP_REFERER"] = "http://www.google.co.uk/search"
42
+ traffic_source = TrafficSource.initialize_with_rack_env(@rack_env, @custom_variable_matches)
43
+ assert_equal "cpc", traffic_source.medium
44
+ assert_equal "MyCamp1", traffic_source.campaign
45
+ assert_equal "Product One", traffic_source.term
46
+ assert_equal Time.now.to_i, traffic_source.unix_timestamp
47
+ assert_equal "1|#{Time.now.to_i}|cpc|Product One|google|MyCamp1", traffic_source.to_s
48
+ end
49
+ end
50
+
51
+ context "when no custom or standard variables matching" do
52
+ context "when there is no referer" do
53
+ should "add create a TrafficSource instance with medium of direct" do
54
+ @rack_env["HTTP_REFERER"] = nil
55
+ traffic_source = TrafficSource.initialize_with_rack_env(@rack_env, @custom_variable_matches)
56
+ assert_equal "direct", traffic_source.medium
57
+ assert_equal Time.now.to_i, traffic_source.unix_timestamp
58
+ assert_equal "1|#{Time.now.to_i}|direct", traffic_source.to_s
59
+ end
60
+ end
61
+
62
+ context "when there is a referer" do
63
+ context "when the referer is an interal address" do
64
+ should "have no medium and to_s return nil" do
65
+ @rack_env["HTTP_REFERER"] = "http://localhost:9393/some/path"
66
+ traffic_source = TrafficSource.initialize_with_rack_env(@rack_env, @custom_variable_matches)
67
+ assert_nil traffic_source.medium
68
+ assert_nil traffic_source.to_s
69
+ end
70
+ end
71
+
72
+ context "when the referer is external" do
73
+ should "have a medium of referer with source and content" do
74
+ @rack_env["HTTP_REFERER"] = "http://matthewfawcett.co.uk/some/path"
75
+ traffic_source = TrafficSource.initialize_with_rack_env(@rack_env, @custom_variable_matches)
76
+ assert_equal "referal", traffic_source.medium
77
+ assert_equal "matthewfawcett.co.uk", traffic_source.source
78
+ assert_equal "/some/path", traffic_source.content
79
+ assert_equal "1|#{Time.now.to_i}|referal||matthewfawcett.co.uk||/some/path", traffic_source.to_s
80
+ end
81
+
82
+ should "assign to a search engine with correct keywords if referer matches" do
83
+ @rack_env["HTTP_REFERER"] = "http://google.co.uk/search?q=mysearchterms"
84
+ traffic_source = TrafficSource.initialize_with_rack_env(@rack_env, @custom_variable_matches)
85
+ assert_equal "organic", traffic_source.medium
86
+ assert_equal "google", traffic_source.source
87
+ assert_equal "mysearchterms", traffic_source.term
88
+ assert_nil traffic_source.content
89
+ assert_equal "1|#{Time.now.to_i}|organic|mysearchterms|google", traffic_source.to_s
90
+ end
91
+ end
92
+ end
93
+ end
94
+
95
+ context "using standard google variables" do
96
+ should "should assign to ppc if the variables say so" do
97
+ @rack_env["rack.request.query_hash"] = {"utm_campaign" => "MyCamp1", "utm_term" => "Product One", "utm_medium" => "cpc", "utm_source" => "google", "utm_term" => "Product One"}
98
+ @rack_env["HTTP_REFERER"] = "http://www.google.co.uk/search"
99
+ traffic_source = TrafficSource.initialize_with_rack_env(@rack_env, @custom_variable_matches)
100
+ assert_equal "cpc", traffic_source.medium
101
+ assert_equal "MyCamp1", traffic_source.campaign
102
+ assert_equal "Product One", traffic_source.term
103
+ assert_equal Time.now.to_i, traffic_source.unix_timestamp
104
+ assert_equal "1|#{Time.now.to_i}|cpc|Product One|google|MyCamp1", traffic_source.to_s
105
+ end
106
+ end
107
+ end
108
+
109
+ context "query_string_value_for" do
110
+ setup do
111
+ @traffic_source = TrafficSource.new
112
+ @traffic_source.custom_parameter_mapping = {:campaign => :custom_campaign, :keyword => :custom_keywords, :medium => :custom_medium}
113
+ end
114
+
115
+ should "use the custom value if there is a match" do
116
+ @traffic_source.env = @rack_env.merge("rack.request.query_hash" => {"custom_campaign" => "mattscustomcampaign", "utm_campaign" => "standardcampaign"})
117
+ assert_equal "mattscustomcampaign", @traffic_source.query_string_value_for(:campaign)
118
+ end
119
+
120
+ should "use the standard value if there is a match and no custom match" do
121
+ @traffic_source.env = @rack_env.merge("rack.request.query_hash" => {"utm_campaign" => "standardcampaign"})
122
+ assert_equal "standardcampaign", @traffic_source.query_string_value_for(:campaign)
123
+ end
124
+
125
+ should "use the standard match if we don't even have any custom parameter mapping" do
126
+ @traffic_source.custom_parameter_mapping = {}
127
+ @traffic_source.env = @rack_env.merge("rack.request.query_hash" => {"custom_campaign" => "mattscustomcampaign", "utm_campaign" => "standardcampaign"})
128
+ assert_equal "standardcampaign", @traffic_source.query_string_value_for(:campaign)
129
+ end
130
+
131
+ should "be nil if no match" do
132
+ @traffic_source.env = @rack_env.merge("rack.request.query_hash" => {})
133
+ assert_nil @traffic_source.query_string_value_for(:campaign)
134
+ end
135
+
136
+ end
137
+
138
+ context "updated_rack_environment" do
139
+
140
+ should "not update the enviroment if the current TrafficSource#to_s is nil" do
141
+ @rack_env["HTTP_REFERER"] = "http://localhost:9393/some/path"
142
+ rack_env = TrafficSource.updated_rack_environment(@rack_env)
143
+ assert_equal "", rack_env["rack.session"][:traffic_sources]
144
+ end
145
+
146
+ should "not update the enviroment if the last TrafficSource#to_s is the same as the current traffic source" do
147
+ @rack_env["HTTP_REFERER"] = nil
148
+ rack_env = TrafficSource.updated_rack_environment(@rack_env)
149
+ assert_equal "1|#{Time.now.to_i}|direct", rack_env["rack.session"][:traffic_sources]
150
+
151
+ rack_env = TrafficSource.updated_rack_environment(@rack_env)
152
+ assert_equal "1|#{Time.now.to_i}|direct", rack_env["rack.session"][:traffic_sources]
153
+ end
154
+
155
+ should "update the traffic source if the current one is differenty from the last one" do
156
+ @rack_env["HTTP_REFERER"] = nil
157
+ rack_env = TrafficSource.updated_rack_environment(@rack_env)
158
+ assert_equal "1|#{Time.now.to_i}|direct", rack_env["rack.session"][:traffic_sources]
159
+
160
+ rack_env["rack.request.query_hash"] = {"utm_campaign" => "MyCamp1", "utm_term" => "Product One", "utm_medium" => "cpc", "utm_source" => "google", "utm_term" => "Product One"}
161
+ rack_env["HTTP_REFERER"] = "http://www.google.co.uk/search"
162
+ rack_env = TrafficSource.updated_rack_environment(@rack_env)
163
+ assert_equal "1|#{Time.now.to_i}|direct,1|#{Time.now.to_i}|cpc|Product One|google|MyCamp1", rack_env["rack.session"][:traffic_sources]
164
+ end
165
+ end
166
+
167
+ end
168
+
169
+
170
+
171
+ context "same_as?" do
172
+ setup do
173
+ @source_1 = TrafficSource.new(:encoder_version => 1, :unix_timestamp => Time.now.to_i, :medium => 'cpc',
174
+ :term => 'myterm', :source => 'google', :campaign => 'mycamp')
175
+ @source_2 = @source_1.dup
176
+ end
177
+
178
+ should "be true if all the main fields are the same" do
179
+ assert @source_1.same_as?(@source_2)
180
+ @source_2.encoder_version = 2
181
+ @source_2.unix_timestamp = 1234
182
+ assert @source_1.same_as?(@source_2)
183
+ end
184
+
185
+ should "be false if one of the fields are different" do
186
+ @source_2.medium = "direct"
187
+ assert !@source_1.same_as?(@source_2)
188
+ end
189
+ end
190
+
191
+ context "initialize_from_string" do
192
+ should "create a new TrafficSource using the correct parameters from the string" do
193
+ string = "1|123456|organic|mysearchterms|google"
194
+ source = TrafficSource.initialize_from_string(string)
195
+ assert_equal 1, source.encoder_version
196
+ assert_equal 123456, source.unix_timestamp
197
+ assert_equal "organic", source.medium
198
+ assert_equal "mysearchterms", source.term
199
+ assert_equal "google", source.source
200
+ assert_nil source.campaign
201
+ assert_nil source.content
202
+ end
203
+ end
204
+
205
+ context "date" do
206
+ should "return a date object using the timestamp" do
207
+ @source = TrafficSource.new(:unix_timestamp => 1267804832)
208
+ assert_equal Time.at(1267804832), @source.date
209
+ end
210
+ end
211
+
212
+
213
+
214
+ end
@@ -0,0 +1,18 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/test_helper')
2
+
3
+ class TrafficSourcesTest < Test::Unit::TestCase
4
+ context "TrafficSourcesTest" do
5
+ context "new" do
6
+ should "allow the raw string to be used to build the array of TrafficSources" do
7
+ assert_equal 2, TrafficSources.new("1|#{Time.now.to_i}|direct,1|#{Time.now.to_i}|cpc|Product One|google|MyCamp1").length
8
+ end
9
+ end
10
+
11
+ context "to_s" do
12
+ should "call to_s on each TrafficSource instance and join with commas" do
13
+ traffic_sources = TrafficSources.new("1|#{Time.now.to_i}|direct,1|#{Time.now.to_i}|cpc|Product One|google|MyCamp1")
14
+ assert_equal "1|#{Time.now.to_i}|direct,1|#{Time.now.to_i}|cpc|Product One|google|MyCamp1", traffic_sources.to_s
15
+ end
16
+ end
17
+ end
18
+ end
metadata ADDED
@@ -0,0 +1,81 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: visitor_sources
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Matt Fawcett
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-03-05 00:00:00 +00:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: thoughtbot-shoulda
17
+ type: :development
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ description: Use a cookie to record the sources that each visitor came to your site
26
+ email: mail@matthewfawcett.co.uk
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - README.md
33
+ files:
34
+ - README.md
35
+ - VERSION
36
+ - lib/visitor_sources.rb
37
+ - lib/visitor_sources/search_engine.rb
38
+ - lib/visitor_sources/traffic_source.rb
39
+ - lib/visitor_sources/traffic_source_middleware.rb
40
+ - lib/visitor_sources/traffic_sources.rb
41
+ - test/app.rb
42
+ - test/search_engine_test.rb
43
+ - test/test_helper.rb
44
+ - test/traffic_source_middleware_test.rb
45
+ - test/traffic_source_test.rb
46
+ - test/traffic_sources_test.rb
47
+ has_rdoc: true
48
+ homepage: http://github.com/mattfawcett/visitor_sources
49
+ licenses: []
50
+
51
+ post_install_message:
52
+ rdoc_options:
53
+ - --charset=UTF-8
54
+ require_paths:
55
+ - lib
56
+ required_ruby_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: "0"
61
+ version:
62
+ required_rubygems_version: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: "0"
67
+ version:
68
+ requirements: []
69
+
70
+ rubyforge_project:
71
+ rubygems_version: 1.3.5
72
+ signing_key:
73
+ specification_version: 3
74
+ summary: Use a cookie to record the sources that each visitor came to your site
75
+ test_files:
76
+ - test/app.rb
77
+ - test/search_engine_test.rb
78
+ - test/test_helper.rb
79
+ - test/traffic_source_middleware_test.rb
80
+ - test/traffic_source_test.rb
81
+ - test/traffic_sources_test.rb