From dafd199b2224ba79ef9a89b5c9e9801e834d4bfe Mon Sep 17 00:00:00 2001 From: Salim Hbeiliny Date: Wed, 6 May 2015 12:55:26 +0200 Subject: [PATCH 1/6] add exact_position option to allow injecting handlers after the opening of the :position tag --- lib/rack/tracker.rb | 6 +++++- .../google_tag_manager/google_tag_manager.rb | 1 + lib/rack/tracker/handler.rb | 3 ++- spec/tracker/tracker_spec.rb | 17 ++++++++++++++++- 4 files changed, 24 insertions(+), 3 deletions(-) diff --git a/lib/rack/tracker.rb b/lib/rack/tracker.rb index 5f298dc..fae3556 100644 --- a/lib/rack/tracker.rb +++ b/lib/rack/tracker.rb @@ -55,7 +55,11 @@ def html?; @headers['Content-Type'] =~ /html/; end def inject(env, response) @handlers.each(env) do |handler| - response.gsub!(%r{}, handler.render + "") + if handler.exact_position == :closing + response.gsub!(%r{}, handler.render + "") + else + response.gsub!(%r{<#{handler.position}>}, "<#{handler.position}>" + handler.render) + end end response end diff --git a/lib/rack/tracker/google_tag_manager/google_tag_manager.rb b/lib/rack/tracker/google_tag_manager/google_tag_manager.rb index be01ed7..42d49a2 100644 --- a/lib/rack/tracker/google_tag_manager/google_tag_manager.rb +++ b/lib/rack/tracker/google_tag_manager/google_tag_manager.rb @@ -18,6 +18,7 @@ def attributes # It is strongly recommended to put the google_tag_manager snippet only in the body tag # https://developers.google.com/tag-manager/quickstart self.position = :body + self.exact_position = :opening def container options[:container].respond_to?(:call) ? options[:container].call(env) : options[:container] diff --git a/lib/rack/tracker/handler.rb b/lib/rack/tracker/handler.rb index bcd2101..9f055d0 100644 --- a/lib/rack/tracker/handler.rb +++ b/lib/rack/tracker/handler.rb @@ -1,6 +1,7 @@ class Rack::Tracker::Handler - class_attribute :position + class_attribute :position, :exact_position self.position = :head + self.exact_position = :closing attr_accessor :options attr_accessor :env diff --git a/spec/tracker/tracker_spec.rb b/spec/tracker/tracker_spec.rb index 1f5a530..c751ff7 100644 --- a/spec/tracker/tracker_spec.rb +++ b/spec/tracker/tracker_spec.rb @@ -12,6 +12,11 @@ class BodyHandler < DummyHandler self.position = :body end +class BodyOpeningHandler < DummyHandler + self.position = :body + self.exact_position = :opening +end + RSpec.describe Rack::Tracker do def app Rack::Builder.new do @@ -20,6 +25,7 @@ def app use Rack::Tracker do handler DummyHandler, { foo: 'head' } handler BodyHandler, { foo: 'body' } + handler BodyOpeningHandler, { foo: 'body_opening' } end run lambda {|env| @@ -55,6 +61,7 @@ def app get '/' expect(last_response.body).to include("console.log('head');") expect(last_response.body).to_not include("console.log('body');") + expect(last_response.body).to_not include("console.log('body_opening');") end it 'injects custom variables that was directly assigned' do @@ -69,11 +76,18 @@ def app end describe 'when body is present' do - it 'will not inject the body handler code' do + it 'will inject only the body handler code' do get '/body' expect(last_response.body).to include("console.log('body');") + expect(last_response.body).to include("console.log('body_opening');") expect(last_response.body).to_not include("console.log('head');") end + + it 'will inject the handlers in their exact_position' do + get '/body' + expect(last_response.body).to include("") + expect(last_response.body).to include("\n") + end end describe 'when head and body is present' do @@ -81,6 +95,7 @@ def app get '/body-head' expect(last_response.body).to include("console.log('head');") expect(last_response.body).to include("console.log('body');") + expect(last_response.body).to include("console.log('body_opening');") end end From abba4a99a5a5bf8ff60cf4eddfccc7d42631cb57 Mon Sep 17 00:00:00 2001 From: Salim Hbeiliny Date: Wed, 6 May 2015 14:42:38 +0200 Subject: [PATCH 2/6] rename position to container_tag and exact_position to container_position --- README.md | 19 ++++++++++++++++--- lib/rack/tracker.rb | 6 +++--- lib/rack/tracker/criteo/criteo.rb | 2 +- lib/rack/tracker/facebook/facebook.rb | 2 +- .../google_adwords_conversion.rb | 2 +- .../google_tag_manager/google_tag_manager.rb | 4 ++-- lib/rack/tracker/handler.rb | 11 ++++++----- spec/handler/criteo_spec.rb | 6 +++--- spec/handler/facebook_spec.rb | 4 ++-- spec/handler/go_squared_spec.rb | 4 ++-- .../handler/google_adwords_conversion_spec.rb | 6 +++--- spec/handler/google_analytics_spec.rb | 6 +++--- spec/handler/google_tag_manager_spec.rb | 10 +++++----- spec/handler/vwo_spec.rb | 4 ++-- spec/integration/criteo_integration_spec.rb | 4 ++-- .../google_analytics_integration_spec.rb | 4 ++-- spec/support/fake_handler.rb | 2 +- spec/tracker/tracker_spec.rb | 8 ++++---- 18 files changed, 59 insertions(+), 45 deletions(-) diff --git a/README.md b/README.md index bd7eb0b..6a0f9b0 100644 --- a/README.md +++ b/README.md @@ -418,17 +418,30 @@ Everything you're passing to the `handler` will be available as `#options` in yo template, so you'll also gain access to the `env`-hash belonging to the current request. Run your application and make a request, the result of the above template can be -found right before ``. You can change the position in your handler-code: +found right before ``. You can change the `container_tag` in your handler-code: ```ruby class MyHandler < Rack::Tracker::Handler - self.position = :body + self.container_tag = :body ... end ``` -The snippit will then be rendered right before ``. +The snippet will then be rendered right before ``. + +You can also change the `container_position` in your handler-code: + +```ruby +class MyHandler < Rack::Tracker::Handler + self.container_tag = :body + self.container_position = :opening + + ... +end +``` + +The snippet will then be rendered right after `` To enable the *tracker dsl* functionality in your controllers you need to implement the `track` class method on your handler: diff --git a/lib/rack/tracker.rb b/lib/rack/tracker.rb index fae3556..30ac441 100644 --- a/lib/rack/tracker.rb +++ b/lib/rack/tracker.rb @@ -55,10 +55,10 @@ def html?; @headers['Content-Type'] =~ /html/; end def inject(env, response) @handlers.each(env) do |handler| - if handler.exact_position == :closing - response.gsub!(%r{}, handler.render + "") + if handler.container_position == :closing + response.gsub!(%r{}, handler.render + "") else - response.gsub!(%r{<#{handler.position}>}, "<#{handler.position}>" + handler.render) + response.gsub!(%r{<#{handler.container_tag}>}, "<#{handler.container_tag}>" + handler.render) end end response diff --git a/lib/rack/tracker/criteo/criteo.rb b/lib/rack/tracker/criteo/criteo.rb index b52a880..8a68f5b 100644 --- a/lib/rack/tracker/criteo/criteo.rb +++ b/lib/rack/tracker/criteo/criteo.rb @@ -13,7 +13,7 @@ def write end end - self.position = :body + self.container_tag = :body # global events (setSiteType, setAccount, ...) for each tracker instance def tracker_events diff --git a/lib/rack/tracker/facebook/facebook.rb b/lib/rack/tracker/facebook/facebook.rb index 3f87247..bdea4db 100644 --- a/lib/rack/tracker/facebook/facebook.rb +++ b/lib/rack/tracker/facebook/facebook.rb @@ -5,7 +5,7 @@ def write end end - self.position = :body + self.container_tag = :body def render Tilt.new( File.join( File.dirname(__FILE__), 'template/facebook.erb') ).render(self) diff --git a/lib/rack/tracker/google_adwords_conversion/google_adwords_conversion.rb b/lib/rack/tracker/google_adwords_conversion/google_adwords_conversion.rb index 68c95ab..b18c3f3 100644 --- a/lib/rack/tracker/google_adwords_conversion/google_adwords_conversion.rb +++ b/lib/rack/tracker/google_adwords_conversion/google_adwords_conversion.rb @@ -3,7 +3,7 @@ class Rack::Tracker::GoogleAdwordsConversion < Rack::Tracker::Handler class Conversion < OpenStruct end - self.position = :body + self.container_tag = :body def render Tilt.new( File.join( File.dirname(__FILE__), 'template', 'google_adwords_conversion.erb') ).render(self) diff --git a/lib/rack/tracker/google_tag_manager/google_tag_manager.rb b/lib/rack/tracker/google_tag_manager/google_tag_manager.rb index 42d49a2..13ec935 100644 --- a/lib/rack/tracker/google_tag_manager/google_tag_manager.rb +++ b/lib/rack/tracker/google_tag_manager/google_tag_manager.rb @@ -17,8 +17,8 @@ def attributes # It is strongly recommended to put the google_tag_manager snippet only in the body tag # https://developers.google.com/tag-manager/quickstart - self.position = :body - self.exact_position = :opening + self.container_tag = :body + self.container_position = :opening def container options[:container].respond_to?(:call) ? options[:container].call(env) : options[:container] diff --git a/lib/rack/tracker/handler.rb b/lib/rack/tracker/handler.rb index 9f055d0..53db3e6 100644 --- a/lib/rack/tracker/handler.rb +++ b/lib/rack/tracker/handler.rb @@ -1,15 +1,16 @@ class Rack::Tracker::Handler - class_attribute :position, :exact_position - self.position = :head - self.exact_position = :closing + class_attribute :container_tag, :container_position + self.container_tag = :head + self.container_position = :closing attr_accessor :options attr_accessor :env def initialize(env, options = {}) self.env = env - self.options = options - self.position = options[:position] if options.has_key?(:position) + self.options = options + self.container_tag = options[:container_tag] if options.has_key?(:container_tag) + self.container_position = options[:container_position] if options.has_key?(:container_position) end def events diff --git a/spec/handler/criteo_spec.rb b/spec/handler/criteo_spec.rb index 8feded3..1fbb94b 100644 --- a/spec/handler/criteo_spec.rb +++ b/spec/handler/criteo_spec.rb @@ -14,8 +14,8 @@ def env end it 'will be placed in the body' do - expect(described_class.position).to eq(:body) - expect(described_class.new(env).position).to eq(:body) + expect(described_class.container_tag).to eq(:body) + expect(described_class.new(env).container_tag).to eq(:body) end describe '#render' do @@ -119,4 +119,4 @@ def env end end -end \ No newline at end of file +end diff --git a/spec/handler/facebook_spec.rb b/spec/handler/facebook_spec.rb index 6a24738..b8cdf42 100644 --- a/spec/handler/facebook_spec.rb +++ b/spec/handler/facebook_spec.rb @@ -13,8 +13,8 @@ def env end it 'will be placed in the body' do - expect(described_class.position).to eq(:body) - expect(described_class.new(env).position).to eq(:body) + expect(described_class.container_tag).to eq(:body) + expect(described_class.new(env).container_tag).to eq(:body) end describe 'with custom audience id' do diff --git a/spec/handler/go_squared_spec.rb b/spec/handler/go_squared_spec.rb index 4d15bab..40a9192 100644 --- a/spec/handler/go_squared_spec.rb +++ b/spec/handler/go_squared_spec.rb @@ -5,8 +5,8 @@ def env end it 'will be placed in the head' do - expect(described_class.position).to eq(:head) - expect(described_class.new(env).position).to eq(:head) + expect(described_class.container_tag).to eq(:head) + expect(described_class.new(env).container_tag).to eq(:head) end describe "with events" do diff --git a/spec/handler/google_adwords_conversion_spec.rb b/spec/handler/google_adwords_conversion_spec.rb index a81dd15..695fef4 100644 --- a/spec/handler/google_adwords_conversion_spec.rb +++ b/spec/handler/google_adwords_conversion_spec.rb @@ -8,9 +8,9 @@ def env end it 'will be placed in the body' do - expect(described_class.position).to eq(:body) - expect(described_class.new(env).position).to eq(:body) - expect(described_class.new(env, position: :body).position).to eq(:body) + expect(described_class.container_tag).to eq(:body) + expect(described_class.new(env).container_tag).to eq(:body) + expect(described_class.new(env, container_tag: :body).container_tag).to eq(:body) end describe "with events" do diff --git a/spec/handler/google_analytics_spec.rb b/spec/handler/google_analytics_spec.rb index 66d842c..22dd603 100644 --- a/spec/handler/google_analytics_spec.rb +++ b/spec/handler/google_analytics_spec.rb @@ -7,9 +7,9 @@ def env end it 'will be placed in the head' do - expect(described_class.position).to eq(:head) - expect(described_class.new(env).position).to eq(:head) - expect(described_class.new(env, position: :body).position).to eq(:body) + expect(described_class.container_tag).to eq(:head) + expect(described_class.new(env).container_tag).to eq(:head) + expect(described_class.new(env, container_tag: :body).container_tag).to eq(:body) end describe '#ecommerce_events' do diff --git a/spec/handler/google_tag_manager_spec.rb b/spec/handler/google_tag_manager_spec.rb index 77f7b1d..38e0ff7 100644 --- a/spec/handler/google_tag_manager_spec.rb +++ b/spec/handler/google_tag_manager_spec.rb @@ -8,9 +8,9 @@ def env end it 'will be placed in the body by default' do - expect(described_class.position).to eq(:body) - expect(described_class.new(env).position).to eq(:body) - expect(described_class.new(env, position: :head).position).to eq(:head) + expect(described_class.container_tag).to eq(:body) + expect(described_class.new(env).container_tag).to eq(:body) + expect(described_class.new(env, container_tag: :head).container_tag).to eq(:head) end describe "with events" do @@ -31,10 +31,10 @@ def env end end - describe "with dynamic tracker" do + describe "with dynamic container" do subject { described_class.new(env, { container: lambda { |env| return env[:misc] }}).render } - it 'will call tracker lambdas to obtain tracking codes' do + it 'will call container lambdas to obtain container codes' do expect(subject).to match(%r{\(window,document,'script','dataLayer','foobar'\)}) end end diff --git a/spec/handler/vwo_spec.rb b/spec/handler/vwo_spec.rb index 5b4fab6..27432e0 100644 --- a/spec/handler/vwo_spec.rb +++ b/spec/handler/vwo_spec.rb @@ -5,8 +5,8 @@ def env end it 'will be placed in the head' do - expect(described_class.position).to eq(:head) - expect(described_class.new(env).position).to eq(:head) + expect(described_class.container_tag).to eq(:head) + expect(described_class.new(env).container_tag).to eq(:head) end end diff --git a/spec/integration/criteo_integration_spec.rb b/spec/integration/criteo_integration_spec.rb index 77364ec..4d919dd 100644 --- a/spec/integration/criteo_integration_spec.rb +++ b/spec/integration/criteo_integration_spec.rb @@ -27,10 +27,10 @@ expect(page.find("body")).to have_content "window.criteo_q.push({\"event\":\"viewBasket\",\"item\":[{\"id\":\"P001\",\"price\":\"6.54\",\"quantity\":1},{\"id\":\"P0038\",\"price\":\"2.99\",\"quantity\":1}]});" end - describe 'adjust tracker position via options' do + describe 'adjust tracker container_tag via options' do before do setup_app(action: :criteo) do |tracker| - tracker.handler :criteo, { set_account: '1234', position: :head } + tracker.handler :criteo, { set_account: '1234', container_tag: :head } end visit '/' end diff --git a/spec/integration/google_analytics_integration_spec.rb b/spec/integration/google_analytics_integration_spec.rb index 14bf48b..320ba0f 100644 --- a/spec/integration/google_analytics_integration_spec.rb +++ b/spec/integration/google_analytics_integration_spec.rb @@ -16,10 +16,10 @@ expect(page.find("head")).to have_content('ga("send",{"hitType":"event","eventCategory":"button","eventAction":"click","eventLabel":"nav-buttons","eventValue":"X"})') end - describe 'adjust tracker position via options' do + describe 'adjust tracker container_tag via options' do before do setup_app(action: :google_analytics) do |tracker| - tracker.handler :google_analytics, { tracker: 'U-XXX-Y', position: :body } + tracker.handler :google_analytics, { tracker: 'U-XXX-Y', container_tag: :body } end visit '/' end diff --git a/spec/support/fake_handler.rb b/spec/support/fake_handler.rb index c40c1e5..b89c6e5 100644 --- a/spec/support/fake_handler.rb +++ b/spec/support/fake_handler.rb @@ -14,7 +14,7 @@ def track_me class AnotherHandler < Rack::Tracker::Handler - self.position = :body + self.container_tag = :body def render Tilt.new( File.join( File.dirname(__FILE__), '../fixtures/another_handler.erb') ).render(self) diff --git a/spec/tracker/tracker_spec.rb b/spec/tracker/tracker_spec.rb index c751ff7..11bc8f5 100644 --- a/spec/tracker/tracker_spec.rb +++ b/spec/tracker/tracker_spec.rb @@ -9,12 +9,12 @@ def dummy_alert end class BodyHandler < DummyHandler - self.position = :body + self.container_tag = :body end class BodyOpeningHandler < DummyHandler - self.position = :body - self.exact_position = :opening + self.container_tag = :body + self.container_position = :opening end RSpec.describe Rack::Tracker do @@ -83,7 +83,7 @@ def app expect(last_response.body).to_not include("console.log('head');") end - it 'will inject the handlers in their exact_position' do + it 'will inject the handlers at their container_position in the container_tag' do get '/body' expect(last_response.body).to include("") expect(last_response.body).to include("\n") From a17b6c0bd8a328ee35071a5dae68ea1ce48d7475 Mon Sep 17 00:00:00 2001 From: Salim Hbeiliny Date: Wed, 6 May 2015 16:41:48 +0200 Subject: [PATCH 3/6] it should still work when container_tag has attributes --- lib/rack/tracker.rb | 4 ++-- spec/tracker/tracker_spec.rb | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/rack/tracker.rb b/lib/rack/tracker.rb index 30ac441..544e36c 100644 --- a/lib/rack/tracker.rb +++ b/lib/rack/tracker.rb @@ -56,9 +56,9 @@ def html?; @headers['Content-Type'] =~ /html/; end def inject(env, response) @handlers.each(env) do |handler| if handler.container_position == :closing - response.gsub!(%r{}, handler.render + "") + response.gsub!(%r{}, handler.render + '\0') else - response.gsub!(%r{<#{handler.container_tag}>}, "<#{handler.container_tag}>" + handler.render) + response.gsub!(%r{<#{handler.container_tag}[^>]*>}, '\0' + handler.render) end end response diff --git a/spec/tracker/tracker_spec.rb b/spec/tracker/tracker_spec.rb index 11bc8f5..455e528 100644 --- a/spec/tracker/tracker_spec.rb +++ b/spec/tracker/tracker_spec.rb @@ -34,7 +34,7 @@ def app when '/' then [200, {'Content-Type' => 'application/html'}, ['Hello world']] when '/body' then - [200, {'Content-Type' => 'application/html'}, ['bob here']] + [200, {'Content-Type' => 'application/html'}, ['bob here']] when '/body-head' then [200, {'Content-Type' => 'application/html'}, ['']] when '/test.xml' then @@ -85,7 +85,7 @@ def app it 'will inject the handlers at their container_position in the container_tag' do get '/body' - expect(last_response.body).to include("") + expect(last_response.body).to include("") expect(last_response.body).to include("\n") end end From f89d54a022b7e5c07e3718da44a24b3b3eb8d44b Mon Sep 17 00:00:00 2001 From: Salim Hbeiliny Date: Thu, 7 May 2015 09:41:45 +0200 Subject: [PATCH 4/6] new position dsl with :append and :prepend options --- README.md | 9 ++++----- lib/rack/tracker.rb | 10 ++++++---- lib/rack/tracker/criteo/criteo.rb | 2 +- lib/rack/tracker/facebook/facebook.rb | 2 +- .../google_adwords_conversion.rb | 2 +- .../google_tag_manager/google_tag_manager.rb | 3 +-- lib/rack/tracker/handler.rb | 19 +++++++++++++------ spec/handler/criteo_spec.rb | 5 +++-- spec/handler/facebook_spec.rb | 5 +++-- spec/handler/go_squared_spec.rb | 5 +++-- .../handler/google_adwords_conversion_spec.rb | 6 +++--- spec/handler/google_analytics_spec.rb | 6 +++--- spec/handler/google_tag_manager_spec.rb | 6 +++--- spec/handler/vwo_spec.rb | 5 +++-- spec/integration/criteo_integration_spec.rb | 8 ++++---- .../google_analytics_integration_spec.rb | 4 ++-- spec/support/fake_handler.rb | 2 +- spec/tracker/tracker_spec.rb | 7 +++---- 18 files changed, 58 insertions(+), 48 deletions(-) diff --git a/README.md b/README.md index 6a0f9b0..6e92a00 100644 --- a/README.md +++ b/README.md @@ -418,11 +418,11 @@ Everything you're passing to the `handler` will be available as `#options` in yo template, so you'll also gain access to the `env`-hash belonging to the current request. Run your application and make a request, the result of the above template can be -found right before ``. You can change the `container_tag` in your handler-code: +found right before ``. You can change the `position` in your handler-code: ```ruby class MyHandler < Rack::Tracker::Handler - self.container_tag = :body + self.position body: :append ... end @@ -430,12 +430,11 @@ end The snippet will then be rendered right before ``. -You can also change the `container_position` in your handler-code: +You can also change the `:append` option to `:prepend` in your handler-code: ```ruby class MyHandler < Rack::Tracker::Handler - self.container_tag = :body - self.container_position = :opening + self.position body: :prepend ... end diff --git a/lib/rack/tracker.rb b/lib/rack/tracker.rb index 544e36c..2dcf25a 100644 --- a/lib/rack/tracker.rb +++ b/lib/rack/tracker.rb @@ -55,10 +55,12 @@ def html?; @headers['Content-Type'] =~ /html/; end def inject(env, response) @handlers.each(env) do |handler| - if handler.container_position == :closing - response.gsub!(%r{}, handler.render + '\0') - else - response.gsub!(%r{<#{handler.container_tag}[^>]*>}, '\0' + handler.render) + handler.position_options.map do |tag, insert| + if insert == :append + response.gsub!(%r{}, handler.render + '\0') + else + response.gsub!(%r{<#{tag}[^>]*>}, '\0' + handler.render) + end end end response diff --git a/lib/rack/tracker/criteo/criteo.rb b/lib/rack/tracker/criteo/criteo.rb index 8a68f5b..a3f75f0 100644 --- a/lib/rack/tracker/criteo/criteo.rb +++ b/lib/rack/tracker/criteo/criteo.rb @@ -13,7 +13,7 @@ def write end end - self.container_tag = :body + self.position body: :append # global events (setSiteType, setAccount, ...) for each tracker instance def tracker_events diff --git a/lib/rack/tracker/facebook/facebook.rb b/lib/rack/tracker/facebook/facebook.rb index bdea4db..06b607c 100644 --- a/lib/rack/tracker/facebook/facebook.rb +++ b/lib/rack/tracker/facebook/facebook.rb @@ -5,7 +5,7 @@ def write end end - self.container_tag = :body + self.position body: :append def render Tilt.new( File.join( File.dirname(__FILE__), 'template/facebook.erb') ).render(self) diff --git a/lib/rack/tracker/google_adwords_conversion/google_adwords_conversion.rb b/lib/rack/tracker/google_adwords_conversion/google_adwords_conversion.rb index b18c3f3..901b4a5 100644 --- a/lib/rack/tracker/google_adwords_conversion/google_adwords_conversion.rb +++ b/lib/rack/tracker/google_adwords_conversion/google_adwords_conversion.rb @@ -3,7 +3,7 @@ class Rack::Tracker::GoogleAdwordsConversion < Rack::Tracker::Handler class Conversion < OpenStruct end - self.container_tag = :body + self.position body: :append def render Tilt.new( File.join( File.dirname(__FILE__), 'template', 'google_adwords_conversion.erb') ).render(self) diff --git a/lib/rack/tracker/google_tag_manager/google_tag_manager.rb b/lib/rack/tracker/google_tag_manager/google_tag_manager.rb index 13ec935..78fa8aa 100644 --- a/lib/rack/tracker/google_tag_manager/google_tag_manager.rb +++ b/lib/rack/tracker/google_tag_manager/google_tag_manager.rb @@ -17,8 +17,7 @@ def attributes # It is strongly recommended to put the google_tag_manager snippet only in the body tag # https://developers.google.com/tag-manager/quickstart - self.container_tag = :body - self.container_position = :opening + self.position body: :prepend def container options[:container].respond_to?(:call) ? options[:container].call(env) : options[:container] diff --git a/lib/rack/tracker/handler.rb b/lib/rack/tracker/handler.rb index 53db3e6..ae644ac 100644 --- a/lib/rack/tracker/handler.rb +++ b/lib/rack/tracker/handler.rb @@ -1,16 +1,14 @@ class Rack::Tracker::Handler - class_attribute :container_tag, :container_position - self.container_tag = :head - self.container_position = :closing + class_attribute :position_options + self.position_options = { head: :append } attr_accessor :options attr_accessor :env def initialize(env, options = {}) self.env = env - self.options = options - self.container_tag = options[:container_tag] if options.has_key?(:container_tag) - self.container_position = options[:container_position] if options.has_key?(:container_position) + self.options = options + self.position_options = options[:position] if options[:position] end def events @@ -25,4 +23,13 @@ def render def self.track(name, event) raise NotImplementedError.new("class method `#{__callee__}` is not implemented.") end + + def self.position(options=nil) + self.position_options = options if options + self.position_options + end + + def position + self.position_options + end end diff --git a/spec/handler/criteo_spec.rb b/spec/handler/criteo_spec.rb index 1fbb94b..26a1a68 100644 --- a/spec/handler/criteo_spec.rb +++ b/spec/handler/criteo_spec.rb @@ -14,8 +14,9 @@ def env end it 'will be placed in the body' do - expect(described_class.container_tag).to eq(:body) - expect(described_class.new(env).container_tag).to eq(:body) + expect(described_class.position).to eq({ body: :append }) + expect(described_class.new(env).position).to eq({ body: :append }) + expect(described_class.new(env, position: { head: :append }).position).to eq({ head: :append }) end describe '#render' do diff --git a/spec/handler/facebook_spec.rb b/spec/handler/facebook_spec.rb index b8cdf42..9230147 100644 --- a/spec/handler/facebook_spec.rb +++ b/spec/handler/facebook_spec.rb @@ -13,8 +13,9 @@ def env end it 'will be placed in the body' do - expect(described_class.container_tag).to eq(:body) - expect(described_class.new(env).container_tag).to eq(:body) + expect(described_class.position).to eq({ body: :append }) + expect(described_class.new(env).position).to eq({ body: :append }) + expect(described_class.new(env, position: { head: :append }).position).to eq({ head: :append }) end describe 'with custom audience id' do diff --git a/spec/handler/go_squared_spec.rb b/spec/handler/go_squared_spec.rb index 40a9192..a25dbd6 100644 --- a/spec/handler/go_squared_spec.rb +++ b/spec/handler/go_squared_spec.rb @@ -5,8 +5,9 @@ def env end it 'will be placed in the head' do - expect(described_class.container_tag).to eq(:head) - expect(described_class.new(env).container_tag).to eq(:head) + expect(described_class.position).to eq({ head: :append }) + expect(described_class.new(env).position).to eq({ head: :append }) + expect(described_class.new(env, position: { body: :append }).position).to eq({ body: :append }) end describe "with events" do diff --git a/spec/handler/google_adwords_conversion_spec.rb b/spec/handler/google_adwords_conversion_spec.rb index 695fef4..c87ba72 100644 --- a/spec/handler/google_adwords_conversion_spec.rb +++ b/spec/handler/google_adwords_conversion_spec.rb @@ -8,9 +8,9 @@ def env end it 'will be placed in the body' do - expect(described_class.container_tag).to eq(:body) - expect(described_class.new(env).container_tag).to eq(:body) - expect(described_class.new(env, container_tag: :body).container_tag).to eq(:body) + expect(described_class.position).to eq({ body: :append }) + expect(described_class.new(env).position).to eq({ body: :append }) + expect(described_class.new(env, position: { head: :append }).position).to eq({ head: :append }) end describe "with events" do diff --git a/spec/handler/google_analytics_spec.rb b/spec/handler/google_analytics_spec.rb index 22dd603..4454d4b 100644 --- a/spec/handler/google_analytics_spec.rb +++ b/spec/handler/google_analytics_spec.rb @@ -7,9 +7,9 @@ def env end it 'will be placed in the head' do - expect(described_class.container_tag).to eq(:head) - expect(described_class.new(env).container_tag).to eq(:head) - expect(described_class.new(env, container_tag: :body).container_tag).to eq(:body) + expect(described_class.position).to eq({ head: :append }) + expect(described_class.new(env).position).to eq({ head: :append }) + expect(described_class.new(env, position: { body: :append }).position).to eq({ body: :append }) end describe '#ecommerce_events' do diff --git a/spec/handler/google_tag_manager_spec.rb b/spec/handler/google_tag_manager_spec.rb index 38e0ff7..65ba30c 100644 --- a/spec/handler/google_tag_manager_spec.rb +++ b/spec/handler/google_tag_manager_spec.rb @@ -8,9 +8,9 @@ def env end it 'will be placed in the body by default' do - expect(described_class.container_tag).to eq(:body) - expect(described_class.new(env).container_tag).to eq(:body) - expect(described_class.new(env, container_tag: :head).container_tag).to eq(:head) + expect(described_class.position).to eq({ body: :prepend }) + expect(described_class.new(env).position).to eq({ body: :prepend }) + expect(described_class.new(env, position: { head: :append }).position).to eq({ head: :append }) end describe "with events" do diff --git a/spec/handler/vwo_spec.rb b/spec/handler/vwo_spec.rb index 27432e0..1de224e 100644 --- a/spec/handler/vwo_spec.rb +++ b/spec/handler/vwo_spec.rb @@ -5,8 +5,9 @@ def env end it 'will be placed in the head' do - expect(described_class.container_tag).to eq(:head) - expect(described_class.new(env).container_tag).to eq(:head) + expect(described_class.position).to eq({ head: :append }) + expect(described_class.new(env).position).to eq({ head: :append }) + expect(described_class.new(env, position: { body: :append }).position).to eq({ body: :append }) end end diff --git a/spec/integration/criteo_integration_spec.rb b/spec/integration/criteo_integration_spec.rb index 4d919dd..dd57a71 100644 --- a/spec/integration/criteo_integration_spec.rb +++ b/spec/integration/criteo_integration_spec.rb @@ -27,17 +27,17 @@ expect(page.find("body")).to have_content "window.criteo_q.push({\"event\":\"viewBasket\",\"item\":[{\"id\":\"P001\",\"price\":\"6.54\",\"quantity\":1},{\"id\":\"P0038\",\"price\":\"2.99\",\"quantity\":1}]});" end - describe 'adjust tracker container_tag via options' do + describe 'adjust tracker position via options' do before do setup_app(action: :criteo) do |tracker| - tracker.handler :criteo, { set_account: '1234', container_tag: :head } + tracker.handler :criteo, { set_account: '1234', position: { head: :append } } end visit '/' end it "will be placed in the specified tag" do - expect(page.find("body")).to_not have_content('criteo') - expect(page.find("head")).to have_content("{\"event\":\"setAccount\",\"account\":\"1234\"}") + expect(page.find("body")).to_not have_content('criteo') + expect(page.find("head")).to have_content("{\"event\":\"setAccount\",\"account\":\"1234\"}") end end diff --git a/spec/integration/google_analytics_integration_spec.rb b/spec/integration/google_analytics_integration_spec.rb index 320ba0f..b2c8cce 100644 --- a/spec/integration/google_analytics_integration_spec.rb +++ b/spec/integration/google_analytics_integration_spec.rb @@ -16,10 +16,10 @@ expect(page.find("head")).to have_content('ga("send",{"hitType":"event","eventCategory":"button","eventAction":"click","eventLabel":"nav-buttons","eventValue":"X"})') end - describe 'adjust tracker container_tag via options' do + describe 'adjust tracker position via options' do before do setup_app(action: :google_analytics) do |tracker| - tracker.handler :google_analytics, { tracker: 'U-XXX-Y', container_tag: :body } + tracker.handler :google_analytics, { tracker: 'U-XXX-Y', position: { body: :append } } end visit '/' end diff --git a/spec/support/fake_handler.rb b/spec/support/fake_handler.rb index b89c6e5..1d11cf6 100644 --- a/spec/support/fake_handler.rb +++ b/spec/support/fake_handler.rb @@ -14,7 +14,7 @@ def track_me class AnotherHandler < Rack::Tracker::Handler - self.container_tag = :body + self.position body: :append def render Tilt.new( File.join( File.dirname(__FILE__), '../fixtures/another_handler.erb') ).render(self) diff --git a/spec/tracker/tracker_spec.rb b/spec/tracker/tracker_spec.rb index 455e528..8a4ead4 100644 --- a/spec/tracker/tracker_spec.rb +++ b/spec/tracker/tracker_spec.rb @@ -9,12 +9,11 @@ def dummy_alert end class BodyHandler < DummyHandler - self.container_tag = :body + self.position body: :append end class BodyOpeningHandler < DummyHandler - self.container_tag = :body - self.container_position = :opening + self.position body: :prepend end RSpec.describe Rack::Tracker do @@ -83,7 +82,7 @@ def app expect(last_response.body).to_not include("console.log('head');") end - it 'will inject the handlers at their container_position in the container_tag' do + it 'will inject the handlers correctly using append or prepend' do get '/body' expect(last_response.body).to include("") expect(last_response.body).to include("\n") From 43f89930e137aea92a19a0757e3f980594a586e4 Mon Sep 17 00:00:00 2001 From: Salim Hbeiliny Date: Thu, 7 May 2015 15:00:07 +0200 Subject: [PATCH 5/6] pre-render handler and inject them once in response --- lib/rack/tracker.rb | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/lib/rack/tracker.rb b/lib/rack/tracker.rb index 2dcf25a..31cee59 100644 --- a/lib/rack/tracker.rb +++ b/lib/rack/tracker.rb @@ -54,15 +54,23 @@ def call(env) def html?; @headers['Content-Type'] =~ /html/; end def inject(env, response) + handlers_by_position = {} + @handlers.each(env) do |handler| - handler.position_options.map do |tag, insert| + handlers_by_position[handler.position_options] = '' if handlers_by_position[handler.position_options].blank? + handlers_by_position[handler.position_options] += handler.render + end + + handlers_by_position.map do |position, rendered_handlers| + position.map do |tag, insert| if insert == :append - response.gsub!(%r{}, handler.render + '\0') + response.sub!(%r{}, rendered_handlers + '\0') else - response.gsub!(%r{<#{tag}[^>]*>}, '\0' + handler.render) + response.sub!(%r{<#{tag}[^>]*>}, '\0' + rendered_handlers) end end end + response end From 2a2398205c5636a111b1aabd2eaea29f43a9d6e6 Mon Sep 17 00:00:00 2001 From: Salim Hbeiliny Date: Fri, 22 May 2015 23:23:28 +0200 Subject: [PATCH 6/6] update position method for zanox --- lib/rack/tracker/zanox/zanox.rb | 2 +- spec/handler/zanox_spec.rb | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/rack/tracker/zanox/zanox.rb b/lib/rack/tracker/zanox/zanox.rb index 580c34e..02a5c8e 100644 --- a/lib/rack/tracker/zanox/zanox.rb +++ b/lib/rack/tracker/zanox/zanox.rb @@ -14,7 +14,7 @@ def write end end - self.position = :body + self.position body: :append def mastertag # First event should be stronger, e.g. one signs up and gets redirected to homepage diff --git a/spec/handler/zanox_spec.rb b/spec/handler/zanox_spec.rb index 4e3090e..ba16091 100644 --- a/spec/handler/zanox_spec.rb +++ b/spec/handler/zanox_spec.rb @@ -13,9 +13,10 @@ def env {} end - it 'will be placed in the body' do - expect(described_class.position).to eq(:body) - expect(described_class.new(env).position).to eq(:body) + it 'will be placed in the body by default' do + expect(described_class.position).to eq({ body: :append }) + expect(described_class.new(env).position).to eq({ body: :append }) + expect(described_class.new(env, position: { head: :append }).position).to eq({ head: :append }) end describe '#render a sale #tracking_event' do