visitor_sources 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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