spree_analytics_trackers 1.0.0 → 2.1.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.
Files changed (75) hide show
  1. checksums.yaml +4 -4
  2. data/.bundle/config +2 -0
  3. data/.gitignore +21 -0
  4. data/.rspec +3 -0
  5. data/.rubocop.yml +2 -0
  6. data/.travis.yml +44 -0
  7. data/Appraisals +11 -0
  8. data/Gemfile +7 -0
  9. data/LICENSE +26 -0
  10. data/README.md +77 -0
  11. data/Rakefile +21 -0
  12. data/app/assets/javascripts/spree/frontend/add_to_cart_analytics.js +50 -0
  13. data/app/assets/javascripts/spree/frontend/remove_from_cart_analytics.js +34 -0
  14. data/app/controllers/spree/admin/trackers_controller.rb +14 -0
  15. data/app/controllers/spree_analytics_trackers/store_controller_decorator.rb +14 -0
  16. data/app/helpers/spree/trackers_helper.rb +86 -0
  17. data/app/models/spree/tracker.rb +31 -0
  18. data/app/models/spree_analytics_trackers/user_decorator.rb +9 -0
  19. data/app/overrides/add_analytics_to_admin_sidebar.rb +8 -0
  20. data/app/overrides/add_cart_viewed_to_orders_edit.rb +10 -0
  21. data/app/overrides/add_checkout_step_viewed_to_checkout_edit.rb +18 -0
  22. data/app/overrides/add_google_analytics_page_view_to_spree_application.rb +10 -0
  23. data/app/overrides/add_google_analytics_to_spree_application.rb +9 -0
  24. data/app/overrides/add_google_purchase_to_orders_show.rb +9 -0
  25. data/app/overrides/add_order_complete_to_orders_show.rb +10 -0
  26. data/app/overrides/add_product_list_filtered_to_taxons_show.rb +10 -0
  27. data/app/overrides/add_product_list_viewed_to_products_list.rb +10 -0
  28. data/app/overrides/add_product_viewed_to_products_show.rb +10 -0
  29. data/app/overrides/add_products_searched_to_products_list.rb +10 -0
  30. data/app/overrides/add_segment_initializer_to_layout.rb +10 -0
  31. data/app/overrides/add_segment_page_viewed_to_layout.rb +10 -0
  32. data/app/presenters/spree_analytics_trackers/base_presenter.rb +14 -0
  33. data/app/presenters/spree_analytics_trackers/segment/order_presenter.rb +32 -0
  34. data/app/presenters/spree_analytics_trackers/segment/product_presenter.rb +40 -0
  35. data/app/views/spree/admin/shared/_analytics_sidebar_menu.html.erb +3 -0
  36. data/app/views/spree/admin/trackers/_form.html.erb +42 -0
  37. data/app/views/spree/admin/trackers/edit.html.erb +13 -0
  38. data/app/views/spree/admin/trackers/index.html.erb +42 -0
  39. data/app/views/spree/admin/trackers/new.html.erb +13 -0
  40. data/app/views/spree/shared/trackers/google_analytics/_checkout_step_viewed.js.erb +19 -0
  41. data/app/views/spree/shared/trackers/google_analytics/_initializer.js.erb +25 -0
  42. data/app/views/spree/shared/trackers/google_analytics/_page_viewed.js.erb +13 -0
  43. data/app/views/spree/shared/trackers/google_analytics/_purchase.js.erb +22 -0
  44. data/app/views/spree/shared/trackers/segment/_cart_viewed.js.erb +27 -0
  45. data/app/views/spree/shared/trackers/segment/_checkout_step_viewed.js.erb +21 -0
  46. data/app/views/spree/shared/trackers/segment/_initializer.js.erb +7 -0
  47. data/app/views/spree/shared/trackers/segment/_order_complete.js.erb +11 -0
  48. data/app/views/spree/shared/trackers/segment/_page_viewed.js.erb +7 -0
  49. data/app/views/spree/shared/trackers/segment/_product_list_filtered.js.erb +23 -0
  50. data/app/views/spree/shared/trackers/segment/_product_list_viewed.js.erb +19 -0
  51. data/app/views/spree/shared/trackers/segment/_product_viewed.js.erb +12 -0
  52. data/app/views/spree/shared/trackers/segment/_products_searched.js.erb +10 -0
  53. data/bin/rails +7 -0
  54. data/config/locales/en.yml +18 -0
  55. data/config/locales/zh-TW.yml +19 -0
  56. data/config/routes.rb +5 -0
  57. data/db/migrate/20171013160337_create_spree_trackers.rb +20 -0
  58. data/db/migrate/20200721163729_add_store_id_to_spree_trackers.rb +14 -0
  59. data/gemfiles/.bundle/config +2 -0
  60. data/gemfiles/spree_4_1.gemfile +9 -0
  61. data/gemfiles/spree_master.gemfile +9 -0
  62. data/lib/generators/spree_analytics_trackers/install/install_generator.rb +28 -0
  63. data/lib/spree_analytics_trackers.rb +5 -0
  64. data/lib/spree_analytics_trackers/engine.rb +20 -0
  65. data/lib/spree_analytics_trackers/factories.rb +10 -0
  66. data/lib/spree_analytics_trackers/version.rb +17 -0
  67. data/spec/features/admin/configuration/analytics_tracker_spec.rb +61 -0
  68. data/spec/features/products_spec.rb +315 -0
  69. data/spec/fixtures/thinking-cat.jpg +0 -0
  70. data/spec/models/spree/tracker_spec.rb +32 -0
  71. data/spec/presenters/spree_analytics_trackers/segment/order_presenter_spec.rb +34 -0
  72. data/spec/spec_helper.rb +18 -0
  73. data/spec/support/custom_products.rb +26 -0
  74. data/spree_analytics_trackers.gemspec +31 -0
  75. metadata +98 -200
@@ -0,0 +1,13 @@
1
+ <% if ga_enabled? %>
2
+ <script>
3
+ if (typeof gtag !== 'undefined') {
4
+ <% if user_id = try_spree_current_user.try(:id) %>
5
+ gtag('config', '<%= ga_tracker.analytics_id %>', {
6
+ 'user_id': '<%= user_id %>'
7
+ });
8
+ <% else %>
9
+ gtag('config', '<%= ga_tracker.analytics_id %>');
10
+ <% end %>
11
+ }
12
+ </script>
13
+ <% end %>
@@ -0,0 +1,22 @@
1
+ <% if ga_enabled? && @order.present? && order_just_completed?(@order) %>
2
+ <script>
3
+ window.addEventListener('turbolinks:load', function() {
4
+ if (typeof gtag !== 'undefined') {
5
+ clearGAplugins();
6
+ gtag('event', 'purchase', {
7
+ transaction_id: '<%= @order.number %>',
8
+ value: <%= @order.total&.to_f %>,
9
+ currency: '<%= @order.currency %>',
10
+ tax: <%= @order.tax_total&.to_f %>,
11
+ shipping: <%= @order.shipment_total&.to_f %>,
12
+ coupon: '<%= @order.promo_code %>',
13
+ items: [
14
+ <% @order.line_items.each do |line_item| %>
15
+ <%= ga_line_item(line_item) %>,
16
+ <% end %>
17
+ ]
18
+ });
19
+ }
20
+ });
21
+ </script>
22
+ <% end %>
@@ -0,0 +1,27 @@
1
+ <% if segment_enabled? && @order.present? && !@order.complete? %>
2
+ <script>
3
+ window.addEventListener('turbolinks:load', function() {
4
+ if (typeof analytics !== 'undefined') {
5
+ var segmentCartJson = {
6
+ cart_id: '<%= @order.number %>',
7
+ products: [
8
+ <% @order.line_items.each_with_index do |line_item, index| %>
9
+ <%=
10
+ product_for_segment(
11
+ line_item.product,
12
+ position: index+1,
13
+ quantity: line_item.quantity,
14
+ image: default_image_for_product_or_variant(line_item.variant)
15
+ )
16
+ %>,
17
+ <% end %>
18
+ ]
19
+ }
20
+
21
+ analytics.track('Cart Viewed', segmentCartJson);
22
+ analytics.page('Cart Viewed', segmentCartJson);
23
+ }
24
+ });
25
+ </script>
26
+ <% end %>
27
+
@@ -0,0 +1,21 @@
1
+ <% if segment_enabled? && @order.present? && !@order.completed? %>
2
+ <script>
3
+ window.addEventListener('turbolinks:load', function() {
4
+ if (typeof analytics !== 'undefined') {
5
+ analytics.track('Checkout Step Viewed',
6
+ {
7
+ checkout_id: '<%= @order.number %>',
8
+ step: '<%= (@order.checkout_steps.index(@order.state) + 1) %>'
9
+ }
10
+ );
11
+
12
+ analytics.page('Checkout Step Viewed',
13
+ {
14
+ checkout_id: '<%= @order.number %>',
15
+ step: '<%= (@order.checkout_steps.index(@order.state) + 1) %>'
16
+ }
17
+ );
18
+ }
19
+ });
20
+ </script>
21
+ <% end %>
@@ -0,0 +1,7 @@
1
+ <% if segment_enabled? %>
2
+ <script>
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('<%=segment_tracker.analytics_id%>'.replace(/^\s+|\s+$/g, ''));
5
+ }}();
6
+ </script>
7
+ <% end %>
@@ -0,0 +1,11 @@
1
+ <% if segment_enabled? && @order.present? && order_just_completed?(@order) %>
2
+ <% order_json = SpreeAnalyticsTrackers::Segment::OrderPresenter.new(@order).to_json %>
3
+ <script>
4
+ window.addEventListener('turbolinks:load', function() {
5
+ if (typeof analytics !== 'undefined') {
6
+ analytics.page('Order Completed', <%= order_json.html_safe %>);
7
+ analytics.track('Order Completed', <%= order_json.html_safe %>);
8
+ }
9
+ });
10
+ </script>
11
+ <% end %>
@@ -0,0 +1,7 @@
1
+ <% if segment_enabled? %>
2
+ <script>
3
+ if (typeof analytics !== 'undefined') {
4
+ analytics.page();
5
+ }
6
+ </script>
7
+ <% end %>
@@ -0,0 +1,23 @@
1
+ <% if segment_enabled? && any_filtering_params? %>
2
+ <script>
3
+ window.addEventListener('turbolinks:load', function() {
4
+ if (typeof analytics !== 'undefined') {
5
+ var segmentProductListFilteredJson = {
6
+ filters: [
7
+ <% filtering_params_with_values.each do |type, value| %>
8
+ <%= { type: type, value: value } .to_json.html_safe %>,
9
+ <% end %>
10
+ ],
11
+ products: [
12
+ <% @products.each_with_index do |product, index| %>
13
+ <%= product_for_segment(product, position: index + 1) %>,
14
+ <% end %>
15
+ ]
16
+ }
17
+
18
+ analytics.track('Product List Filtered', segmentProductListFilteredJson);
19
+ analytics.page('Product List Filtered', segmentProductListFilteredJson);
20
+ }
21
+ });
22
+ </script>
23
+ <% end %>
@@ -0,0 +1,19 @@
1
+ <% if segment_enabled? && defined?(products) && products.present? %>
2
+ <script>
3
+ window.addEventListener('turbolinks:load', function() {
4
+ if (typeof analytics !== 'undefined') {
5
+ var segmentProductListViewedJson = {
6
+ category: '<%= @taxon&.name %>',
7
+ products: [
8
+ <% products.each_with_index do |product, index| %>
9
+ <%= product_for_segment(product, position: index+1, image: default_image_for_product_or_variant(product)) %>,
10
+ <% end %>
11
+ ]
12
+ }
13
+
14
+ analytics.track('Product List Viewed', segmentProductListViewedJson);
15
+ analytics.page('Product List Viewed', segmentProductListViewedJson);
16
+ }
17
+ });
18
+ </script>
19
+ <% end %>
@@ -0,0 +1,12 @@
1
+ <% if segment_enabled? && @product.present? %>
2
+ <script>
3
+ window.addEventListener('turbolinks:load', function() {
4
+ if (typeof analytics !== 'undefined') {
5
+ var segmentProductViewed = <%= product_for_segment(@product, image: default_image_for_product_or_variant(@product)) %>;
6
+
7
+ analytics.page('Product Viewed', segmentProductViewed);
8
+ analytics.track('Product Viewed', segmentProductViewed);
9
+ }
10
+ });
11
+ </script>
12
+ <% end %>
@@ -0,0 +1,10 @@
1
+ <% if segment_enabled? && params.key?(:keywords) && params[:keywords].present? %>
2
+ <script>
3
+ window.addEventListener('turbolinks:load', function() {
4
+ if (typeof analytics !== 'undefined') {
5
+ analytics.track('Products Searched', { query: '<%= params[:keywords] %>' });
6
+ analytics.page('Products Searched', { query: '<%= params[:keywords] %>' });
7
+ }
8
+ });
9
+ </script>
10
+ <% end %>
@@ -0,0 +1,7 @@
1
+ # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
2
+
3
+ ENGINE_ROOT = File.expand_path('../..', __FILE__)
4
+ ENGINE_PATH = File.expand_path('../../lib/spree_analytics_trackers/engine', __FILE__)
5
+
6
+ require 'rails/all'
7
+ require 'rails/engine/commands'
@@ -0,0 +1,18 @@
1
+ en:
2
+ activerecord:
3
+ attributes:
4
+ spree/tracker:
5
+ one: Tracker
6
+ other: Trackers
7
+ spree:
8
+ analytics_engine: Analytics Engine
9
+ analytics_trackers: Analytics Trackers
10
+ new_tracker: New Tracker
11
+ google_analytics: Google Analytics
12
+ google_analytics_id: Analytics ID
13
+ analytics_desc_header_1: Spree Analytics
14
+ analytics_desc_header_2: Live analytics integrated into your Spree dashboard
15
+ analytics_desc_list_1: Get live sales information as it happens
16
+ analytics_desc_list_2: Requires only a free Spree account to activate
17
+ analytics_desc_list_3: Absolutely no code to install
18
+ analytics_desc_list_4: It's completely free!
@@ -0,0 +1,19 @@
1
+ zh-TW:
2
+ activerecord:
3
+ attributes:
4
+ spree/tracker:
5
+ one: 追蹤器
6
+ other: 追蹤器
7
+ spree:
8
+ analytics_engine: 分析引擎
9
+ analytics_trackers: 分析追蹤器
10
+ new_tracker: 新增追蹤器
11
+ google_analytics: Google 分析
12
+ google_analytics_id: Google 追蹤器代碼
13
+ analytics_desc_header_1: Spree 分析
14
+ analytics_desc_header_2: 新增即時分析到 Spree 的後台
15
+ analytics_desc_list_1: 獲得即時銷售數據
16
+ analytics_desc_list_2: 免費安裝
17
+ analytics_desc_list_3: 不需要寫任何代碼安裝
18
+ analytics_desc_list_4: 完全免費!
19
+
@@ -0,0 +1,5 @@
1
+ Spree::Core::Engine.add_routes do
2
+ namespace :admin, path: Spree.admin_path do
3
+ resources :trackers
4
+ end
5
+ end
@@ -0,0 +1,20 @@
1
+ class CreateSpreeTrackers < SpreeExtension::Migration[4.2]
2
+ def change
3
+ if table_exists?(:spree_trackers)
4
+ add_index :spree_trackers, :active unless index_exists?(:spree_trackers, :active)
5
+ remove_column :spree_trackers, :environment if column_exists?(:spree_trackers, :environment)
6
+ unless column_exists?(:spree_trackers, :engine)
7
+ add_column :spree_trackers, :kind, :integer, default: 0, null: false, index: true unless column_exists?(:spree_trackers, :kind)
8
+ rename_column :spree_trackers, :kind, :engine if column_exists?(:spree_trackers, :kind)
9
+ end
10
+ else
11
+ create_table :spree_trackers do |t|
12
+ t.string 'analytics_id'
13
+ t.boolean 'active', default: true, index: true
14
+ t.datetime 'created_at', null: false
15
+ t.datetime 'updated_at', null: false
16
+ t.integer 'engine', default: 0, null: false, index: true
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,14 @@
1
+ class AddStoreIdToSpreeTrackers < ActiveRecord::Migration[6.0]
2
+ def change
3
+ add_column :spree_trackers, :store_id, :integer
4
+ add_index :spree_trackers, :store_id
5
+
6
+ Spree::Tracker.reset_column_information
7
+
8
+ default_store = Spree::Store.default
9
+ Spree::Tracker.all.each do |tracker|
10
+ tracker.store = default_store
11
+ tracker.save
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,2 @@
1
+ ---
2
+ BUNDLE_RETRY: "1"
@@ -0,0 +1,9 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "spree", "~> 4.1.0"
6
+ gem "spree_auth_devise", "~> 4.1.0"
7
+ gem "rails-controller-testing"
8
+
9
+ gemspec path: "../"
@@ -0,0 +1,9 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "spree", github: "spree/spree", branch: "master"
6
+ gem "spree_auth_devise", github: "spree/spree_auth_devise", branch: "master"
7
+ gem "rails-controller-testing"
8
+
9
+ gemspec path: "../"
@@ -0,0 +1,28 @@
1
+ module SpreeAnalyticsTrackers
2
+ module Generators
3
+ class InstallGenerator < Rails::Generators::Base
4
+ class_option :auto_run_migrations, type: :boolean, default: false
5
+
6
+ def add_javascripts
7
+ javascripts_path = 'vendor/assets/javascripts/spree/frontend/all.js'
8
+ return unless File.file?(javascripts_path)
9
+
10
+ append_file 'vendor/assets/javascripts/spree/frontend/all.js', "//= require spree/frontend/add_to_cart_analytics\n"
11
+ append_file 'vendor/assets/javascripts/spree/frontend/all.js', "//= require spree/frontend/remove_from_cart_analytics\n"
12
+ end
13
+
14
+ def add_migrations
15
+ run 'bundle exec rake railties:install:migrations FROM=spree_analytics_trackers'
16
+ end
17
+
18
+ def run_migrations
19
+ run_migrations = options[:auto_run_migrations] || ['', 'y', 'Y'].include?(ask 'Would you like to run the migrations now? [Y/n]')
20
+ if run_migrations
21
+ run 'bundle exec rake db:migrate'
22
+ else
23
+ puts 'Skipping rake db:migrate, don\'t forget to run it!'
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,5 @@
1
+ require 'spree_core'
2
+ require 'spree_extension'
3
+ require 'spree_analytics_trackers/engine'
4
+ require 'spree_analytics_trackers/version'
5
+ require 'deface'
@@ -0,0 +1,20 @@
1
+ module SpreeAnalyticsTrackers
2
+ class Engine < Rails::Engine
3
+ require 'spree/core'
4
+ isolate_namespace Spree
5
+ engine_name 'spree_analytics_trackers'
6
+
7
+ # use rspec for tests
8
+ config.generators do |g|
9
+ g.test_framework :rspec
10
+ end
11
+
12
+ def self.activate
13
+ Dir.glob(File.join(File.dirname(__FILE__), '../../app/**/*_decorator*.rb')) do |c|
14
+ Rails.configuration.cache_classes ? require(c) : load(c)
15
+ end
16
+ end
17
+
18
+ config.to_prepare &method(:activate).to_proc
19
+ end
20
+ end
@@ -0,0 +1,10 @@
1
+ unless FactoryBot.factories.registered?(:tracker)
2
+ FactoryBot.define do
3
+ factory :tracker, class: Spree::Tracker do
4
+ analytics_id { 'A100' }
5
+ active { true }
6
+ engine { :google_analytics }
7
+ store { Spree::Store.default || create(:store) }
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,17 @@
1
+ module SpreeAnalyticsTrackers
2
+ module_function
3
+
4
+ # Returns the version of the currently loaded SpreeAnalyticsTrackers as a
5
+ # <tt>Gem::Version</tt>.
6
+ def version
7
+ Gem::Version.new VERSION::STRING
8
+ end
9
+
10
+ module VERSION
11
+ MAJOR = 2
12
+ MINOR = 1
13
+ TINY = 0
14
+
15
+ STRING = [MAJOR, MINOR, TINY].compact.join('.')
16
+ end
17
+ end
@@ -0,0 +1,61 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Analytics Tracker', type: :feature do
4
+ stub_authorization!
5
+
6
+ let!(:default_store) { Spree::Store.default }
7
+ let!(:another_store) { create(:store, name: 'Eurozone') }
8
+
9
+ context 'index' do
10
+ before(:each) do
11
+ create(:tracker, store: default_store)
12
+ create(:tracker, analytics_id: 'A200', store: another_store)
13
+ visit spree.admin_trackers_path
14
+ end
15
+
16
+ it 'should have the right content' do
17
+ expect(page).to have_content('Analytics Trackers')
18
+ end
19
+
20
+ it 'should have the right tabular values displayed' do
21
+ within_row(1) do
22
+ expect(column_text(1)).to eq('A100')
23
+ expect(column_text(2)).to eq('Google analytics')
24
+ expect(column_text(3)).to eq(default_store.name)
25
+ expect(column_text(4)).to eq('Yes')
26
+ end
27
+
28
+ within_row(2) do
29
+ expect(column_text(1)).to eq('A200')
30
+ expect(column_text(2)).to eq('Google analytics')
31
+ expect(column_text(3)).to eq('Eurozone')
32
+ expect(column_text(4)).to eq('Yes')
33
+ end
34
+ end
35
+ end
36
+
37
+ context 'create' do
38
+ before(:each) do
39
+ visit spree.admin_trackers_path
40
+ end
41
+
42
+ it 'should be able to create a new analytics tracker', js: true do
43
+ within('.content-header') do
44
+ click_link 'admin_new_tracker_link'
45
+ end
46
+ fill_in 'tracker_analytics_id', with: 'A100'
47
+
48
+ select2 default_store.name, from: 'Store'
49
+
50
+ click_button 'Create'
51
+
52
+ expect(page).to have_content('successfully created!')
53
+ within_row(1) do
54
+ expect(column_text(1)).to eq('A100')
55
+ expect(column_text(2)).to eq('Google analytics')
56
+ expect(column_text(3)).to eq(default_store.name)
57
+ expect(column_text(4)).to eq('Yes')
58
+ end
59
+ end
60
+ end
61
+ end