spree_analytics_trackers 1.1.0 → 2.0.0.rc1

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.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +2 -0
  3. data/.travis.yml +30 -36
  4. data/Appraisals +3 -16
  5. data/LICENSE +1 -1
  6. data/README.md +7 -3
  7. data/app/assets/javascripts/spree/frontend/add_to_cart_analytics.js +46 -0
  8. data/app/controllers/spree_analytics_trackers/store_controller_decorator.rb +6 -3
  9. data/app/helpers/spree/trackers_helper.rb +58 -20
  10. data/app/overrides/add_cart_viewed_to_orders_edit.rb +1 -1
  11. data/app/overrides/add_checkout_step_viewed_to_checkout_edit.rb +11 -3
  12. data/app/overrides/add_google_analytics_page_view_to_spree_application.rb +18 -0
  13. data/app/overrides/add_google_analytics_to_spree_application.rb +11 -3
  14. data/app/overrides/add_google_purchase_to_orders_show.rb +1 -1
  15. data/app/overrides/add_product_list_filtered_to_taxons_show.rb +1 -1
  16. data/app/overrides/add_product_list_viewed_to_products_list.rb +1 -1
  17. data/app/overrides/add_product_viewed_to_products_show.rb +2 -2
  18. data/app/overrides/add_products_searched_to_products_list.rb +2 -2
  19. data/app/overrides/add_segment_initializer_to_layout.rb +10 -2
  20. data/app/overrides/add_segment_page_viewed_to_layout.rb +18 -0
  21. data/app/presenters/spree_analytics_trackers/base_presenter.rb +14 -0
  22. data/app/presenters/spree_analytics_trackers/segment/order_presenter.rb +32 -0
  23. data/app/presenters/spree_analytics_trackers/segment/product_presenter.rb +40 -0
  24. data/app/views/spree/shared/trackers/google_analytics/_checkout_step_viewed.js.erb +21 -0
  25. data/app/views/spree/shared/trackers/google_analytics/_initializer.js.erb +11 -0
  26. data/app/views/spree/shared/trackers/google_analytics/_page_viewed.js.erb +13 -0
  27. data/app/views/spree/shared/trackers/google_analytics/_purchase.js.erb +19 -0
  28. data/app/views/spree/shared/trackers/segment/_cart_viewed.js.erb +21 -21
  29. data/app/views/spree/shared/trackers/segment/_checkout_step_viewed.js.erb +14 -12
  30. data/app/views/spree/shared/trackers/segment/_initializer.js.erb +1 -2
  31. data/app/views/spree/shared/trackers/segment/_order_complete.js.erb +3 -43
  32. data/app/views/spree/shared/trackers/segment/_page_viewed.js.erb +7 -0
  33. data/app/views/spree/shared/trackers/segment/_product_list_filtered.js.erb +7 -18
  34. data/app/views/spree/shared/trackers/segment/_product_list_viewed.js.erb +16 -21
  35. data/app/views/spree/shared/trackers/segment/_product_viewed.js.erb +10 -6
  36. data/app/views/spree/shared/trackers/segment/_products_searched.js.erb +1 -1
  37. data/config/locales/en.yml +0 -2
  38. data/config/locales/zh-TW.yml +19 -0
  39. data/gemfiles/{spree_3_5.gemfile → spree_4_1.gemfile} +2 -2
  40. data/gemfiles/spree_master.gemfile +0 -1
  41. data/lib/generators/spree_analytics_trackers/install/install_generator.rb +7 -0
  42. data/lib/spree_analytics_trackers.rb +1 -0
  43. data/lib/spree_analytics_trackers/version.rb +4 -3
  44. data/spec/features/admin/configuration/analytics_tracker_spec.rb +3 -1
  45. data/spec/features/products_spec.rb +315 -0
  46. data/spec/fixtures/thinking-cat.jpg +0 -0
  47. data/spec/presenters/spree_analytics_trackers/segment/order_presenter_spec.rb +34 -0
  48. data/spec/spec_helper.rb +7 -82
  49. data/spec/support/custom_products.rb +26 -0
  50. data/spree_analytics_trackers.gemspec +3 -17
  51. metadata +36 -220
  52. data/app/overrides/add_google_checkout_to_checkout_edit.rb +0 -9
  53. data/app/overrides/add_product_added_to_orders_edit.rb +0 -10
  54. data/app/views/spree/shared/_google_add_items.html.erb +0 -13
  55. data/app/views/spree/shared/_google_analytics.html.erb +0 -18
  56. data/app/views/spree/shared/_google_checkout.html.erb +0 -14
  57. data/app/views/spree/shared/_google_purchase.html.erb +0 -19
  58. data/app/views/spree/shared/trackers/segment/_product_added.js.erb +0 -9
  59. data/gemfiles/spree_3_7.gemfile +0 -10
  60. data/gemfiles/spree_4_0.gemfile +0 -9
@@ -1,9 +1,9 @@
1
1
  spree_version = Gem.loaded_specs['spree_core'].version
2
2
  unless spree_version >= Gem::Version.create('3.4.0') && spree_version < Gem::Version.create('3.5.0')
3
3
  Deface::Override.new(
4
- virtual_path: 'spree/shared/_products',
4
+ virtual_path: 'spree/products/index',
5
5
  name: 'add_products_searched_to_products_list',
6
- insert_before: "[data-hook='products_search_results_heading']",
6
+ insert_before: '[data-hook="search_results"]',
7
7
  partial: 'spree/shared/trackers/segment/products_searched.js',
8
8
  original: '8b47dddca9dfaaacca3d462459c6c1ef06c09926'
9
9
  )
@@ -3,8 +3,16 @@ unless spree_version >= Gem::Version.create('3.3.0') && spree_version < Gem::Ver
3
3
  Deface::Override.new(
4
4
  virtual_path: 'spree/layouts/spree_application',
5
5
  name: 'add_segment_initializer_to_layout',
6
- insert_top: "[data-hook='body']",
6
+ insert_bottom: '[data-hook="inside_head"]',
7
7
  partial: 'spree/shared/trackers/segment/initializer.js',
8
- original: '26b91c1073b75c93c9e9c89b1f0a6f52ef29a8f9'
8
+ original: '6841b819babbe4df1f03d0bc8e05dc81bf0d45ad'
9
+ )
10
+
11
+ Deface::Override.new(
12
+ virtual_path: 'spree/layouts/checkout',
13
+ name: 'add_segment_initializer_to_spree_checkout',
14
+ insert_bottom: '[data-hook="inside_head"]',
15
+ partial: 'spree/shared/trackers/segment/initializer.js',
16
+ original: '6841b819babbe4df1f03d0bc8e05dc81bf0d45ad'
9
17
  )
10
18
  end
@@ -0,0 +1,18 @@
1
+ spree_version = Gem.loaded_specs['spree_core'].version
2
+ unless spree_version >= Gem::Version.create('3.3.0') && spree_version < Gem::Version.create('3.5.0') && spree_version != Gem::Version.create('3.5.0.alpha')
3
+ Deface::Override.new(
4
+ virtual_path: 'spree/layouts/spree_application',
5
+ name: 'add_segment_page_tracker_to_body',
6
+ insert_bottom: "[data-hook='body']",
7
+ partial: 'spree/shared/trackers/segment/page_viewed.js',
8
+ original: '6841b819babbe4df1f03d0bc8e05dc81bf0d45ad'
9
+ )
10
+
11
+ Deface::Override.new(
12
+ virtual_path: 'spree/layouts/checkout',
13
+ name: 'add_segment_page_tracker_to_spree_checkout',
14
+ insert_bottom: "[data-hook='body']",
15
+ partial: 'spree/shared/trackers/segment/page_viewed.js',
16
+ original: '6841b819babbe4df1f03d0bc8e05dc81bf0d45ad'
17
+ )
18
+ end
@@ -0,0 +1,14 @@
1
+ module SpreeAnalyticsTrackers
2
+ class BasePresenter
3
+ include Rails.application.routes.url_helpers
4
+
5
+ def initialize(resource = {}, options = {})
6
+ @resource = resource
7
+ @options = options
8
+ end
9
+
10
+ def to_json
11
+ serialize_resource(@resource, @options).to_json
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,32 @@
1
+ module SpreeAnalyticsTrackers
2
+ module Segment
3
+ class OrderPresenter < SpreeAnalyticsTrackers::BasePresenter
4
+ private
5
+
6
+ def serialize_resource(resource, options = {})
7
+ {
8
+ order_id: resource.number.to_s,
9
+ total: resource.total&.to_f,
10
+ shipping: resource.shipment_total&.to_f,
11
+ tax: resource.additional_tax_total&.to_f,
12
+ discount: resource.promo_total&.to_f,
13
+ coupon: resource.promo_code,
14
+ currency: resource.currency,
15
+ products: resource.line_items.map { |li| serialize_line_item(li) }
16
+ }
17
+ end
18
+
19
+ private
20
+
21
+ def serialize_line_item(line_item)
22
+ {
23
+ product_id: line_item.product_id&.to_s,
24
+ sku: line_item.sku&.to_s,
25
+ name: line_item.name,
26
+ price: line_item.price&.to_f,
27
+ quantity: line_item.quantity
28
+ }
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,40 @@
1
+ module SpreeAnalyticsTrackers
2
+ module Segment
3
+ class ProductPresenter < SpreeAnalyticsTrackers::BasePresenter
4
+ private
5
+
6
+ def serialize_resource(resource, options = {})
7
+ {
8
+ resource_id: resource.id.to_s,
9
+ sku: resource.sku&.to_s,
10
+ category: resource.category&.name,
11
+ name: resource.name,
12
+ brand: brand_name,
13
+ price: resource.price_in(current_currency).amount&.to_f,
14
+ currency: current_currency,
15
+ url: resource_url(resource)
16
+ }.tap do |hash|
17
+ hash[:image_url] = segment_image_url(hash, options)
18
+ end.merge(options)
19
+ end
20
+
21
+ def segment_image_url(hash, options)
22
+
23
+ end
24
+
25
+ def brand_name
26
+ resource.vendor.name if defined?(SpreeMultiVendor) && resource.defined?(:vendor) && resource.vendor.present?
27
+
28
+ resource.brand&.name
29
+ end
30
+
31
+ def current_currency
32
+ @current_currency ||= options[:current_currency]
33
+ end
34
+
35
+ def locale
36
+ @locale ||= options[:locale]
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,21 @@
1
+ <% if @order.present? && !@order.completed? && Spree::Tracker.current(:google_analytics) %>
2
+ <script>
3
+ if (typeof gtag !== 'undefined') {
4
+ gtag('event', 'checkout_progress', {
5
+ checkout_step: '<%= (@order.checkout_steps.index(@order.state) + 1) %>',
6
+ items: [
7
+ <% @order.line_items.each do |line_item| %>
8
+ <%= ga_line_item(line_item) %>,
9
+ <% end %>
10
+ ],
11
+
12
+ coupon: '<%= @order.promo_code %>',
13
+ });
14
+
15
+ gtag('event', 'set_checkout_option', {
16
+ 'checkout_step': '<%= (@order.checkout_steps.index(@order.state) + 1) %>',
17
+ 'checkout_option': '<%= @order.state %>'
18
+ });
19
+ };
20
+ </script>
21
+ <% end %>
@@ -0,0 +1,11 @@
1
+ <% if tracker = Spree::Tracker.current(:google_analytics) %>
2
+ <!-- Global site tag (gtag.js) - Google Analytics -->
3
+ <script async src="https://www.googletagmanager.com/gtag/js?id=<%= tracker.analytics_id %>"></script>
4
+ <script>
5
+ window.dataLayer = window.dataLayer || [];
6
+ function gtag(){dataLayer.push(arguments);}
7
+ gtag('js', new Date());
8
+
9
+ gtag('config', '<%= tracker.analytics_id %>', { 'send_page_view': false });
10
+ </script>
11
+ <% end %>
@@ -0,0 +1,13 @@
1
+ <% if tracker = Spree::Tracker.current(:google_analytics) %>
2
+ <script>
3
+ if (typeof gtag !== 'undefined') {
4
+ <% if user_id = try_spree_current_user.try(:id) %>
5
+ gtag('config', '<%= tracker.analytics_id %>', {
6
+ 'user_id': '<%= user_id %>'
7
+ });
8
+ <% else %>
9
+ gtag('config', '<%= tracker.analytics_id %>');
10
+ <% end %>
11
+ }
12
+ </script>
13
+ <% end %>
@@ -0,0 +1,19 @@
1
+ <% if @order.present? && order_just_completed?(@order) && Spree::Tracker.current(:google_analytics) %>
2
+ <script>
3
+ if (typeof gtag !== 'undefined') {
4
+ gtag('event', 'purchase', {
5
+ transaction_id: '<%= @order.number %>',
6
+ value: <%= @order.total&.to_f %>,
7
+ currency: '<%= @order.currency %>',
8
+ tax: <%= @order.tax_total&.to_f %>,
9
+ shipping: <%= @order.shipment_total&.to_f %>,
10
+ coupon: '<%= @order.promo_code %>',
11
+ items: [
12
+ <% @order.line_items.each do |line_item| %>
13
+ <%= ga_line_item(line_item) %>,
14
+ <% end %>
15
+ ]
16
+ });
17
+ }
18
+ </script>
19
+ <% end %>
@@ -1,22 +1,22 @@
1
- <script>
2
- if (typeof analytics !== 'undefined') {
3
- analytics.track('Cart Viewed', {
4
- cart_id: '<%= @order.number %>',
5
- products: [
6
- <% @order.line_items.each_with_index do |line_item, index| %>
7
- <%= product_for_segment(line_item, position: index+1, quantity: line_item.quantity) %>,
8
- <% end %>
9
- ]
10
- });
1
+ <% if @order.present? && !@order.complete? && Spree::Tracker.current(:segment) %>
2
+ <script>
3
+ if (typeof analytics !== 'undefined') {
4
+ var segmentCartJson = {
5
+ cart_id: '<%= @order.number %>',
6
+ products: [
7
+ <% @order.line_items.each_with_index do |line_item, index| %>
8
+ <%= product_for_segment(
9
+ line_item.product,
10
+ position: index+1,
11
+ quantity: line_item.quantity,
12
+ image: default_image_for_product_or_variant(line_item.variant)
13
+ ) %>,
14
+ <% end %>
15
+ ]
16
+ }
11
17
 
12
- analytics.page('Cart Viewed', {
13
- cart_id: '<%= @order.number %>',
14
- products: [
15
- <% @order.line_items.each_with_index do |line_item, index| %>
16
- <%= product_for_segment(line_item, position: index+1, quantity: line_item.quantity) %>,
17
- <% end %>
18
- ]
19
- });
20
-
21
- }
22
- </script>
18
+ analytics.track('Cart Viewed', segmentCartJson);
19
+ analytics.page('Cart Viewed', segmentCartJson);
20
+ }
21
+ </script>
22
+ <% end %>
@@ -1,12 +1,14 @@
1
- <script>
2
- if (typeof analytics !== 'undefined') {
3
- analytics.track('Checkout Step Viewed', {
4
- checkout_id: '<%= @order.number %>',
5
- step: '<%= (@order.checkout_steps.index(@order.state) + 1) %>'
6
- });
7
- analytics.page('Checkout Step Viewed', {
8
- checkout_id: '<%= @order.number %>',
9
- step: '<%= (@order.checkout_steps.index(@order.state) + 1) %>'
10
- });
11
- }
12
- </script>
1
+ <% if @order.present? && !@order.completed? && Spree::Tracker.current(:segment) %>
2
+ <script>
3
+ if (typeof analytics !== 'undefined') {
4
+ analytics.track('Checkout Step Viewed', {
5
+ checkout_id: '<%= @order.number %>',
6
+ step: '<%= (@order.checkout_steps.index(@order.state) + 1) %>'
7
+ });
8
+ analytics.page('Checkout Step Viewed', {
9
+ checkout_id: '<%= @order.number %>',
10
+ step: '<%= (@order.checkout_steps.index(@order.state) + 1) %>'
11
+ });
12
+ }
13
+ </script>
14
+ <% end %>
@@ -1,8 +1,7 @@
1
1
  <% if tracker = Spree::Tracker.current(:segment) %>
2
2
  <script>
3
3
  !function(){var analytics=window.analytics=window.analytics||[];if(!analytics.initialize)if(analytics.invoked)window.console&&console.error&&console.error("Segment snippet included twice.");else{analytics.invoked=!0;analytics.methods=["trackSubmit","trackClick","trackLink","trackForm","pageview","identify","reset","group","track","ready","alias","debug","page","once","off","on"];analytics.factory=function(t){return function(){var e=Array.prototype.slice.call(arguments);e.unshift(t);analytics.push(e);return analytics}};for(var t=0;t<analytics.methods.length;t++){var e=analytics.methods[t];analytics[e]=analytics.factory(e)}analytics.load=function(t,e){var n=document.createElement("script");n.type="text/javascript";n.async=!0;n.src="https://cdn.segment.com/analytics.js/v1/"+t+"/analytics.min.js";var a=document.getElementsByTagName("script")[0];a.parentNode.insertBefore(n,a);analytics._loadOptions=e};analytics.SNIPPET_VERSION="4.1.0";
4
- analytics.load('<%=tracker.analytics_id%>'.replace(/^\s+|\s+$/g, ''));
5
- analytics.page()
4
+ analytics.load('<%=tracker.analytics_id%>'.replace(/^\s+|\s+$/g, ''));
6
5
  }}();
7
6
  </script>
8
7
  <% end %>
@@ -1,48 +1,8 @@
1
- <% if order_just_completed?(@order) %>
1
+ <% if @order.present? && order_just_completed?(@order) && Spree::Tracker.current(:segment) %>
2
+ <% order_json = SpreeAnalyticsTrackers::Segment::OrderPresenter.new(@order).to_json %>
2
3
  <script>
3
4
  if (typeof analytics !== 'undefined') {
4
- analytics.track('Order Completed', {
5
- order_id: '<%= @order.number %>',
6
- total: <%= @order.total %>,
7
- shipping: <%= @order.shipment_total %>,
8
- tax: <%= @order.additional_tax_total %>,
9
- discount: <%= @order.promo_total %>,
10
- coupon: '<%= @order.promo_code %>',
11
- currency: '<%= @order.currency %>',
12
- products: [
13
- <% @order.line_items.each do |line_item| %>
14
- {
15
- product_id: '<%= line_item.product.id %>',
16
- sku: '<%= line_item.variant.sku %>',
17
- name: '<%= line_item.product.name %>',
18
- price: <%= line_item.price %>,
19
- quantity: <%= line_item.quantity %>
20
- },
21
- <% end %>
22
- ]
23
- });
24
-
25
- analytics.page('Order Completed', {
26
- order_id: '<%= @order.number %>',
27
- total: <%= @order.total %>,
28
- shipping: <%= @order.shipment_total %>,
29
- tax: <%= @order.additional_tax_total %>,
30
- discount: <%= @order.promo_total %>,
31
- coupon: '<%= @order.promo_code %>',
32
- currency: '<%= @order.currency %>',
33
- products: [
34
- <% @order.line_items.each do |line_item| %>
35
- {
36
- product_id: '<%= line_item.product.id %>',
37
- sku: '<%= line_item.variant.sku %>',
38
- name: '<%= line_item.product.name %>',
39
- price: <%= line_item.price %>,
40
- quantity: <%= line_item.quantity %>
41
- },
42
- <% end %>
43
- ]
44
- });
45
-
5
+ analytics.page('Order Completed', <%= order_json.html_safe %>);
46
6
  }
47
7
  </script>
48
8
  <% end %>
@@ -0,0 +1,7 @@
1
+ <% if tracker = Spree::Tracker.current(:segment) %>
2
+ <script>
3
+ if (typeof analytics !== 'undefined') {
4
+ analytics.page();
5
+ }
6
+ </script>
7
+ <% end %>
@@ -1,32 +1,21 @@
1
- <% if params[:search].present? %>
1
+ <% if any_filtering_params? && Spree::Tracker.current(:segment) %>
2
2
  <script>
3
3
  if (typeof analytics !== 'undefined') {
4
- analytics.track('Product List Filtered', {
4
+ var segmentProductListFilteredJson = {
5
5
  filters: [
6
- <% params[:search].to_unsafe_h.each do |type, value| %>
6
+ <% filtering_params_with_values.each do |type, value| %>
7
7
  <%= { type: type, value: value } .to_json.html_safe %>,
8
8
  <% end %>
9
9
  ],
10
10
  products: [
11
11
  <% @products.each_with_index do |product, index| %>
12
- <%= product_for_segment(product, position: index+1, image: product.images.first) %>,
12
+ <%= product_for_segment(product, position: index+1) %>,
13
13
  <% end %>
14
14
  ]
15
- });
16
-
17
- analytics.page('Product List Filtered', {
18
- filters: [
19
- <% params[:search].to_unsafe_h.each do |type, value| %>
20
- <%= { type: type, value: value } .to_json.html_safe %>,
21
- <% end %>
22
- ],
23
- products: [
24
- <% @products.each_with_index do |product, index| %>
25
- <%= product_for_segment(product, position: index+1, image: product.images.first) %>,
26
- <% end %>
27
- ]
28
- });
15
+ }
29
16
 
17
+ analytics.track('Product List Filtered', segmentProductListFilteredJson);
18
+ analytics.page('Product List Filtered', segmentProductListFilteredJson);
30
19
  }
31
20
  </script>
32
21
  <% end %>
@@ -1,22 +1,17 @@
1
- <script>
2
- if (typeof analytics !== 'undefined') {
3
- analytics.track('Product List Viewed', {
4
- category: '<%= @taxon.try(:name) %>',
5
- products: [
6
- <% products.each_with_index do |product, index| %>
7
- <%= product_for_segment(product, position: index+1, image: product.images.first) %>,
8
- <% end %>
9
- ]
10
- });
1
+ <% if defined?(products) && products.present? && Spree::Tracker.current(:segment) %>
2
+ <script>
3
+ if (typeof analytics !== 'undefined') {
4
+ var segmentProductListViewedJson = {
5
+ category: '<%= @taxon&.name %>',
6
+ products: [
7
+ <% products.each_with_index do |product, index| %>
8
+ <%= product_for_segment(product, position: index+1, image: default_image_for_product_or_variant(product)) %>,
9
+ <% end %>
10
+ ]
11
+ }
11
12
 
12
- analytics.page('Product List Viewed', {
13
- category: '<%= @taxon.try(:name) %>',
14
- products: [
15
- <% products.each_with_index do |product, index| %>
16
- <%= product_for_segment(product, position: index+1, image: product.images.first) %>,
17
- <% end %>
18
- ]
19
- });
20
-
21
- }
22
- </script>
13
+ analytics.track('Product List Viewed', segmentProductListViewedJson);
14
+ analytics.page('Product List Viewed', segmentProductListViewedJson);
15
+ }
16
+ </script>
17
+ <% end %>
@@ -1,6 +1,10 @@
1
- <script>
2
- if (typeof analytics !== 'undefined') {
3
- analytics.track('Product Viewed', <%= product_for_segment(@product, image: @product.images.first) %>);
4
- analytics.page('Product Viewed', <%= product_for_segment(@product, image: @product.images.first) %>);
5
- }
6
- </script>
1
+ <% if @product.present? && Spree::Tracker.current(:segment) %>
2
+ <script>
3
+ if (typeof analytics !== 'undefined') {
4
+ var segmentProductViewed = <%= product_for_segment(@product, image: default_image_for_product_or_variant(@product)) %>;
5
+
6
+ analytics.page('Product Viewed', segmentProductViewed);
7
+ analytics.track('Product Viewed', segmentProductViewed);
8
+ }
9
+ </script>
10
+ <% end %>