spree_google_analytics 1.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.
Files changed (33) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.md +14 -0
  3. data/README.md +61 -0
  4. data/Rakefile +21 -0
  5. data/app/assets/config/spree_google_analytics_manifest.js +1 -0
  6. data/app/assets/images/integration_icons/google-analytics-logo.png +0 -0
  7. data/app/controllers/spree_google_analytics/store_controller_decorator.rb +9 -0
  8. data/app/helpers/spree_google_analytics/base_helper.rb +81 -0
  9. data/app/models/spree/integrations/google_analytics.rb +17 -0
  10. data/app/presenters/spree_google_analytics/checkout_presenter.rb +12 -0
  11. data/app/presenters/spree_google_analytics/order_presenter.rb +59 -0
  12. data/app/presenters/spree_google_analytics/payment_presenter.rb +7 -0
  13. data/app/presenters/spree_google_analytics/product_presenter.rb +54 -0
  14. data/app/views/spree/admin/integrations/forms/_google_analytics.html.erb +16 -0
  15. data/app/views/spree_google_analytics/_add_to_cart.html.erb +9 -0
  16. data/app/views/spree_google_analytics/_add_to_wishlist.erb +9 -0
  17. data/app/views/spree_google_analytics/_body_end.html.erb +27 -0
  18. data/app/views/spree_google_analytics/_cart.html.erb +11 -0
  19. data/app/views/spree_google_analytics/_checkout_complete.html.erb +15 -0
  20. data/app/views/spree_google_analytics/_head.html.erb +34 -0
  21. data/app/views/spree_google_analytics/_product.html.erb +7 -0
  22. data/app/views/spree_google_analytics/_remove_from_cart.html.erb +9 -0
  23. data/config/initializers/spree.rb +17 -0
  24. data/config/locales/en.yml +10 -0
  25. data/config/routes.rb +3 -0
  26. data/lib/generators/spree_google_analytics/install/install_generator.rb +20 -0
  27. data/lib/spree_google_analytics/configuration.rb +13 -0
  28. data/lib/spree_google_analytics/engine.rb +28 -0
  29. data/lib/spree_google_analytics/factories.rb +3 -0
  30. data/lib/spree_google_analytics/testing_support/factories/google_analytics_integration.rb +7 -0
  31. data/lib/spree_google_analytics/version.rb +7 -0
  32. data/lib/spree_google_analytics.rb +5 -0
  33. metadata +130 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 6c60f82dafa6c0ddced33284212aab54aaee082b7f2099cfd864e709774b3a54
4
+ data.tar.gz: a0fa0447fa1a82e9ddf06c4b1eb9153bc72e92206dd5a085c2d6f3f1334320c9
5
+ SHA512:
6
+ metadata.gz: 4e7f62f44a99df591d50f0f77fec46088f47bc64e598567beb94a661949527d2c8a839c5311635d8a2bffbd70a47be02e4223bb3baf0643de25710abffc1a151
7
+ data.tar.gz: 84ed673c296694e8cfe422fcd99413ce4547db6d62a0ba7853f988a473b94ff270be41b173b943f0ce5a63923caac14dca73f32beb67482be2e20a7c02f119e3
data/LICENSE.md ADDED
@@ -0,0 +1,14 @@
1
+ # LICENSE
2
+
3
+ Copyright (c) 2025 Vendo Connect Inc.
4
+ All rights reserved.
5
+
6
+ This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
7
+
8
+ This program is distributed in the hope that it will be useful,
9
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ GNU Affero General Public License for more details.
12
+
13
+ You should have received a copy of the GNU Affero General Public License
14
+ along with this program. If not, see [https://www.gnu.org/licenses/](https://www.gnu.org/licenses/).
data/README.md ADDED
@@ -0,0 +1,61 @@
1
+ # Spree Google analytics
2
+
3
+ This is a Google analytics extension for [Spree Commerce](https://spreecommerce.org), an open source e-commerce platform built with Ruby on Rails.
4
+
5
+ ## Installation
6
+
7
+ 1. Add this extension to your Gemfile with this line:
8
+
9
+ ```ruby
10
+ bundle add spree_google_analytics
11
+ ```
12
+
13
+ 2. Run the install generator
14
+
15
+ ```ruby
16
+ bundle exec rails g spree_google_analytics:install
17
+ ```
18
+
19
+ 3. Restart your server
20
+
21
+ If your server was running, restart it so that it can find the assets properly.
22
+
23
+ ## Developing
24
+
25
+ 1. Create a dummy app
26
+
27
+ ```bash
28
+ bundle update
29
+ bundle exec rake test_app
30
+ ```
31
+
32
+ 2. Add your new code
33
+ 3. Run tests
34
+
35
+ ```bash
36
+ bundle exec rspec
37
+ ```
38
+
39
+ When testing your applications integration with this extension you may use it's factories.
40
+ Simply add this require statement to your spec_helper:
41
+
42
+ ```ruby
43
+ require 'spree_google_analytics/factories'
44
+ ```
45
+
46
+ ## Releasing a new version
47
+
48
+ ```shell
49
+ bundle exec gem bump -p -t
50
+ bundle exec gem release
51
+ ```
52
+
53
+ For more options please see [gem-release README](https://github.com/svenfuchs/gem-release)
54
+
55
+ ## Contributing
56
+
57
+ If you'd like to contribute, please take a look at the
58
+ [instructions](CONTRIBUTING.md) for installing dependencies and crafting a good
59
+ pull request.
60
+
61
+ Copyright (c) 2025 [name of extension creator], released under the New BSD License
data/Rakefile ADDED
@@ -0,0 +1,21 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rspec/core/rake_task'
5
+ require 'spree/testing_support/extension_rake'
6
+
7
+ RSpec::Core::RakeTask.new
8
+
9
+ task :default do
10
+ if Dir['spec/dummy'].empty?
11
+ Rake::Task[:test_app].invoke
12
+ Dir.chdir('../../')
13
+ end
14
+ Rake::Task[:spec].invoke
15
+ end
16
+
17
+ desc 'Generates a dummy app for testing'
18
+ task :test_app do
19
+ ENV['LIB_NAME'] = 'spree_google_analytics'
20
+ Rake::Task['extension:test_app'].invoke
21
+ end
@@ -0,0 +1 @@
1
+ //= link_tree ../images
@@ -0,0 +1,9 @@
1
+ module SpreeGoogleAnalytics
2
+ module StoreControllerDecorator
3
+ def self.prepended(base)
4
+ base.helper SpreeGoogleAnalytics::BaseHelper
5
+ end
6
+ end
7
+ end
8
+
9
+ Spree::StoreController.prepend(SpreeGoogleAnalytics::StoreControllerDecorator) if defined?(Spree::StoreController)
@@ -0,0 +1,81 @@
1
+ module SpreeGoogleAnalytics
2
+ module BaseHelper
3
+ def google_analytics_checkout_json
4
+ return unless @order.present?
5
+
6
+ @google_analytics_checkout_json ||= SpreeGoogleAnalytics::CheckoutPresenter.new(order: @order).call.to_json.html_safe
7
+ end
8
+
9
+ def google_analytics_add_shipping_info_json(shipment)
10
+ SpreeGoogleAnalytics::CheckoutPresenter.new(order: shipment.order).call.merge({ shipping_tier: shipment.shipping_method&.name }).to_json.html_safe
11
+ end
12
+
13
+ def google_analytics_user_properties_json(user)
14
+ return unless user.present?
15
+
16
+ {
17
+ sign_in_count: user.sign_in_count,
18
+ created_at: user.created_at&.iso8601.to_s,
19
+ completed_orders_count: user.orders.complete.count,
20
+ completed_orders_total: user.orders.complete.sum(:total).to_f
21
+ }.to_json.html_safe
22
+ end
23
+
24
+ def google_analytics_payment_json
25
+ return unless @order.present?
26
+
27
+ @google_analytics_payment_json ||= SpreeGoogleAnalytics::PaymentPresenter.new(order: @order).call.to_json.html_safe
28
+ end
29
+
30
+ def google_analytics_purchase_json
31
+ return unless @order.present?
32
+
33
+ @google_analytics_purchase_json ||= SpreeGoogleAnalytics::OrderPresenter.new(order: @order).call.to_json.html_safe
34
+ end
35
+
36
+ def google_analytics_view_item_json(variant = nil)
37
+ variant ||= @selected_variant || @variant_from_options || @product&.default_variant
38
+ return unless variant.present?
39
+
40
+ {
41
+ currency: current_currency,
42
+ value: variant.amount_in(current_currency).to_f,
43
+ items: [
44
+ SpreeGoogleAnalytics::ProductPresenter.new(
45
+ store_name: current_store.name,
46
+ resource: variant,
47
+ quantity: 1
48
+ ).call
49
+ ]
50
+ }.to_json.html_safe
51
+ end
52
+
53
+ def google_analytics_cart_event_json(line_item, quantity, position)
54
+ {
55
+ currency: line_item.currency,
56
+ value: line_item.amount.to_f,
57
+ items: [
58
+ SpreeGoogleAnalytics::ProductPresenter.new(
59
+ resource: line_item,
60
+ quantity: quantity,
61
+ position: position
62
+ ).call
63
+ ]
64
+ }.to_json.html_safe
65
+ end
66
+
67
+ def google_analytics_add_to_wishlist_event_json(variant)
68
+ {
69
+ currency: current_currency,
70
+ value: variant.amount_in(current_currency),
71
+ items: [
72
+ SpreeGoogleAnalytics::ProductPresenter.new(
73
+ store_name: current_store.name,
74
+ resource: variant,
75
+ quantity: 1
76
+ ).call
77
+ ]
78
+ }.to_json.html_safe
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,17 @@
1
+ module Spree
2
+ module Integrations
3
+ class GoogleAnalytics < Spree::Integration
4
+ preference :measurement_id, :string
5
+
6
+ validates :preferred_measurement_id, presence: true
7
+
8
+ def self.integration_group
9
+ 'analytics'
10
+ end
11
+
12
+ def self.icon_path
13
+ 'integration_icons/google-analytics-logo.png'
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,12 @@
1
+ module SpreeGoogleAnalytics
2
+ class CheckoutPresenter < OrderPresenter
3
+ def call
4
+ {
5
+ currency: @order.currency,
6
+ value: @order.analytics_subtotal,
7
+ coupon: try_coupon_code,
8
+ items: products(@order)
9
+ }.merge(try_debug_mode)
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,59 @@
1
+ module SpreeGoogleAnalytics
2
+ class OrderPresenter
3
+ include Spree::BaseHelper
4
+
5
+ def initialize(order:)
6
+ @order = order
7
+ end
8
+
9
+ def call
10
+ {
11
+ currency: @order.currency,
12
+ transaction_id: @order.number,
13
+ value: @order.analytics_subtotal,
14
+ coupon: try_coupon_code,
15
+ shipping: @order.shipment_total.to_f,
16
+ tax: @order.additional_tax_total.to_f,
17
+ items: products(@order)
18
+ }.merge(try_debug_mode)
19
+ .merge(gift_card_attributes)
20
+ end
21
+
22
+ private
23
+
24
+ def products(order)
25
+ return [] if order.line_items.empty?
26
+
27
+ product_includes = %i[taxons]
28
+ product_includes << :vendor if defined?(Spree::Vendor)
29
+
30
+ @products ||= order.line_items.includes(variant: { product: product_includes }).map.with_index do |line_item, index|
31
+ ProductPresenter.new(
32
+ resource: line_item,
33
+ quantity: line_item.quantity,
34
+ position: index + 1
35
+ ).call
36
+ end
37
+ end
38
+
39
+ def try_debug_mode
40
+ ENV['GA_DEBUG_MODE'].present? ? { debug_mode: 1 } : {}
41
+ end
42
+
43
+ def try_coupon_code
44
+ (@order.coupon_code || @order.try(:gift_card).try(:code)).to_s
45
+ end
46
+
47
+ def gift_card_attributes
48
+ return {} unless defined?(Spree::GiftCard)
49
+ return {} unless @order.gift_card.present?
50
+
51
+ {
52
+ gift_card_code: @order.gift_card&.code.to_s.upcase,
53
+ gift_card_amount: @order.gift_card_total.to_f,
54
+ gift_card_balance: @order.gift_card&.amount_remaining.to_f,
55
+ total_minus_store_credits: @order.total_minus_store_credits.to_f
56
+ }
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,7 @@
1
+ module SpreeGoogleAnalytics
2
+ class PaymentPresenter < CheckoutPresenter
3
+ def call
4
+ super.merge({ payment_type: @order.payments&.last&.payment_method&.name })
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,54 @@
1
+ module SpreeGoogleAnalytics
2
+ class ProductPresenter
3
+ include Spree::BaseHelper
4
+ include Spree::ProductsHelper
5
+
6
+ # @param resource [Spree::LineItem, Spree::Variant]
7
+ # @param quantity [Integer]
8
+ # @param position [Integer]
9
+ # @param store_name [String]
10
+ def initialize(resource:, quantity:, position: nil, store_name: nil)
11
+ @resource = resource
12
+ @quantity = quantity
13
+ @position = position
14
+ @store_name = store_name
15
+ end
16
+
17
+ # @return [Hash]
18
+ def call
19
+ {
20
+ item_id: @resource.sku.presence || @resource.product_id,
21
+ item_name: @resource.name,
22
+ affiliation: @resource.respond_to?(:order) && @resource.order&.store.present? ? @resource.order.store.name : @store_name,
23
+ discount: 0.00,
24
+ index: @position.to_s,
25
+ item_brand: @resource.product.present? ? @resource.product.brand_name.to_s : '',
26
+ item_category: taxons[0].to_s,
27
+ item_category2: taxons[1].to_s,
28
+ item_category3: taxons[2].to_s,
29
+ item_category4: taxons[3].to_s,
30
+ item_category5: taxons[4].to_s,
31
+ item_list_id: '',
32
+ item_list_name: '',
33
+ item_variant: @resource.try(:options_text),
34
+ location_id: '',
35
+ price: @resource.price.to_f,
36
+ quantity: @quantity
37
+ }.merge(try_promotion_codes_applied_to_line_item)
38
+ end
39
+
40
+ private
41
+
42
+ def try_promotion_codes_applied_to_line_item
43
+ return {} if @resource.class != Spree::LineItem
44
+
45
+ { coupon: @resource.adjustments.promotion.map do |adjustment|
46
+ adjustment.source.promotion.code
47
+ end.compact.uniq.join(',') }
48
+ end
49
+
50
+ def taxons
51
+ @taxons ||= @resource.product.main_taxon&.pretty_name.to_s.split('->').map(&:strip)
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,16 @@
1
+ <div class="col-12 col-md-6 p-0">
2
+ <div class="card mb-4">
3
+ <div class="card-body">
4
+ <% if @integration.persisted? %>
5
+ <div class="alert alert-warning">
6
+ <%= Spree.t('admin.integrations.google_analytics.reports_warning') %>
7
+ </div>
8
+ <% end %>
9
+
10
+ <%= preference_field(@integration, form, 'measurement_id', i18n_scope: 'admin.integrations.google_analytics') %>
11
+ <p class="mb-0 mt-2">
12
+ <%= external_link_to 'Where to find my Measurement ID?', 'https://support.google.com/analytics/answer/12270356' %>
13
+ </p>
14
+ </div>
15
+ </div>
16
+ </div>
@@ -0,0 +1,9 @@
1
+ <% if store_integration('google_analytics').present? %>
2
+ <script>
3
+ if (window.gtag) {
4
+ <% safely do %>
5
+ gtag('event', 'add_to_cart', <%= google_analytics_cart_event_json(@line_item, @line_item.quantity, @order.line_items.pluck(:id).index(@line_item.id) + 1) %>);
6
+ <% end %>
7
+ }
8
+ </script>
9
+ <% end %>
@@ -0,0 +1,9 @@
1
+ <% if store_integration('google_analytics').present? && @wished_item&.variant.present? %>
2
+ <script>
3
+ if (window.gtag) {
4
+ <% safely do %>
5
+ gtag('event', 'add_to_wishlist', <%= google_analytics_add_to_wishlist_event_json(@wished_item.variant) %>);
6
+ <% end %>
7
+ }
8
+ </script>
9
+ <% end %>
@@ -0,0 +1,27 @@
1
+ <% if store_integration('google_analytics').present? %>
2
+ <script>
3
+ if (window.gtag) {
4
+ <% if controller_name == 'checkout' %>
5
+ <% if @order && session[:checkout_started] %>
6
+ <% safely do %>
7
+ gtag('event', 'begin_checkout', <%= google_analytics_checkout_json %>);
8
+ <% end %>
9
+ <% end %>
10
+
11
+ <% if @order && session[:checkout_step_completed] == 'delivery' %>
12
+ <% safely do %>
13
+ <% @order.shipments.each do |shipment| %>
14
+ gtag('event', 'add_shipping_info', <%= google_analytics_add_shipping_info_json(shipment) %>);
15
+ <% end %>
16
+ <% end %>
17
+ <% end %>
18
+ <% end %>
19
+
20
+ <% if controller_name == 'search' && action_name == 'show' && query.present? %>
21
+ <% safely do %>
22
+ gtag('event', 'search', <%= raw({ search_term: ERB::Util.html_escape(query) }.to_json) %>);
23
+ <% end %>
24
+ <% end %>
25
+ }
26
+ </script>
27
+ <% end %>
@@ -0,0 +1,11 @@
1
+ <% if store_integration('google_analytics').present? %>
2
+ <script>
3
+ if (window.gtag) {
4
+ <% if @order.present? && @line_items.any? %>
5
+ window.addEventListener('slideover:open', () => {
6
+ gtag('event', 'view_cart', <%= google_analytics_checkout_json %>);
7
+ })
8
+ <% end %>
9
+ }
10
+ </script>
11
+ <% end %>
@@ -0,0 +1,15 @@
1
+ <% if store_integration('google_analytics').present? %>
2
+ <script>
3
+ if (window.gtag) {
4
+ <% safely do %>
5
+ <% if @order.user.present? %>
6
+ gtag('set', 'user_id', "<%= @order.reload.user_id %>");
7
+ gtag('set', 'user_properties', <%= google_analytics_user_properties_json(@order.user) %>);
8
+ <% end %>
9
+
10
+ gtag('event', 'add_payment_info', <%= google_analytics_payment_json %>);
11
+ gtag('event', 'purchase', <%= google_analytics_purchase_json %>);
12
+ <% end %>
13
+ }
14
+ </script>
15
+ <% end %>
@@ -0,0 +1,34 @@
1
+ <% if store_integration('google_analytics').present? %>
2
+ <!-- Google tag (gtag.js) -->
3
+ <script async src="https://www.googletagmanager.com/gtag/js?id=<%= store_integration('google_analytics').preferred_measurement_id %>"></script>
4
+ <script>
5
+ window.dataLayer = window.dataLayer || [];
6
+ function gtag(){dataLayer.push(arguments);}
7
+
8
+ <% if defined?(store_integration('cookie_first')) && store_integration('cookie_first').present? %>
9
+ gtag('consent', 'default', {
10
+ 'ad_storage': 'denied',
11
+ 'ad_user_data': 'denied',
12
+ 'ad_personalization': 'denied',
13
+ 'analytics_storage': 'denied',
14
+ 'functionality_storage': 'denied',
15
+ 'security_storage': 'granted',
16
+ 'wait_for_update': 2000
17
+ });
18
+ <% end %>
19
+
20
+ gtag('js', new Date());
21
+ GA_MEASUREMENT_ID = "<%= store_integration('google_analytics').preferred_measurement_id %>";
22
+
23
+ <% if ENV['GA_DEBUG_MODE'].present? %>
24
+ gtag('config', GA_MEASUREMENT_ID, { "debug_mode": true });
25
+ <% else %>
26
+ gtag('config', GA_MEASUREMENT_ID);
27
+ <% end %>
28
+
29
+ <% if try_spree_current_user %>
30
+ gtag('set', 'user_id', "<%= try_spree_current_user.id %>");
31
+ gtag('set', 'user_properties', <%= google_analytics_user_properties_json(try_spree_current_user) %>);
32
+ <% end %>
33
+ </script>
34
+ <% end %>
@@ -0,0 +1,7 @@
1
+ <% if store_integration('google_analytics').present? %>
2
+ <script>
3
+ if (window.gtag) {
4
+ gtag('event', 'view_item', <%= google_analytics_view_item_json %>);
5
+ }
6
+ </script>
7
+ <% end %>
@@ -0,0 +1,9 @@
1
+ <% if store_integration('google_analytics').present? %>
2
+ <script>
3
+ if (window.gtag) {
4
+ <% safely do %>
5
+ gtag('event', 'remove_from_cart', <%= google_analytics_cart_event_json(@line_item, @line_item.quantity, nil) %>);
6
+ <% end %>
7
+ }
8
+ </script>
9
+ <% end %>
@@ -0,0 +1,17 @@
1
+ Rails.application.config.after_initialize do
2
+ Rails.application.config.spree.integrations << Spree::Integrations::GoogleAnalytics
3
+
4
+ if Rails.application.config.respond_to?(:spree_storefront)
5
+ Rails.application.config.spree_storefront.head_partials << 'spree_google_analytics/head'
6
+ Rails.application.config.spree_storefront.body_end_partials << 'spree_google_analytics/body_end'
7
+
8
+ Rails.application.config.spree_storefront.cart_partials << 'spree_google_analytics/cart'
9
+ Rails.application.config.spree_storefront.add_to_cart_partials << 'spree_google_analytics/add_to_cart'
10
+ Rails.application.config.spree_storefront.remove_from_cart_partials << 'spree_google_analytics/remove_from_cart'
11
+
12
+ Rails.application.config.spree_storefront.checkout_complete_partials << 'spree_google_analytics/checkout_complete'
13
+
14
+ Rails.application.config.spree_storefront.product_partials << 'spree_google_analytics/product'
15
+ Rails.application.config.spree_storefront.add_to_wishlist_partials << 'spree_google_analytics/add_to_wishlist'
16
+ end
17
+ end
@@ -0,0 +1,10 @@
1
+ ---
2
+ en:
3
+ spree:
4
+ admin:
5
+ integrations:
6
+ google_analytics:
7
+ description: Google Analytics 4 is a powerful tool that helps businesses understand and analyze their website and app data.
8
+ reports_warning: It can take up to 48 hours for the data to appear in standard reports
9
+ measurement_id: Measurement ID
10
+ api_secret: API Secret
data/config/routes.rb ADDED
@@ -0,0 +1,3 @@
1
+ Spree::Core::Engine.add_routes do
2
+ # Add your extension routes here
3
+ end
@@ -0,0 +1,20 @@
1
+ module SpreeGoogleAnalytics
2
+ module Generators
3
+ class InstallGenerator < Rails::Generators::Base
4
+ class_option :migrate, type: :boolean, default: true
5
+
6
+ def add_migrations
7
+ run 'bundle exec rake railties:install:migrations FROM=spree_google_analytics'
8
+ end
9
+
10
+ def run_migrations
11
+ run_migrations = options[:migrate] || ['', 'y', 'Y'].include?(ask('Would you like to run the migrations now? [Y/n]'))
12
+ if run_migrations
13
+ run 'bin/rails db:migrate'
14
+ else
15
+ puts 'Skipping rails db:migrate, don\'t forget to run it!'
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,13 @@
1
+ module SpreeGoogleAnalytics
2
+ class Configuration < Spree::Preferences::Configuration
3
+
4
+ # Some example preferences are shown below, for more information visit:
5
+ # https://docs.spreecommerce.org/developer/contributing/creating-an-extension
6
+
7
+ # preference :enabled, :boolean, default: true
8
+ # preference :dark_chocolate, :boolean, default: true
9
+ # preference :color, :string, default: 'Red'
10
+ # preference :favorite_number, :integer
11
+ # preference :supported_locales, :array, default: [:en]
12
+ end
13
+ end
@@ -0,0 +1,28 @@
1
+ module SpreeGoogleAnalytics
2
+ class Engine < Rails::Engine
3
+ require 'spree/core'
4
+ isolate_namespace Spree
5
+ engine_name 'spree_google_analytics'
6
+
7
+ # use rspec for tests
8
+ config.generators do |g|
9
+ g.test_framework :rspec
10
+ end
11
+
12
+ initializer 'spree_google_analytics.environment', before: :load_config_initializers do |_app|
13
+ SpreeGoogleAnalytics::Config = SpreeGoogleAnalytics::Configuration.new
14
+ end
15
+
16
+ initializer 'spree_google_analytics.assets' do |app|
17
+ app.config.assets.precompile += %w[spree_google_analytics_manifest]
18
+ end
19
+
20
+ def self.activate
21
+ Dir.glob(File.join(File.dirname(__FILE__), '../../app/**/*_decorator*.rb')) do |c|
22
+ Rails.configuration.cache_classes ? require(c) : load(c)
23
+ end
24
+ end
25
+
26
+ config.to_prepare(&method(:activate).to_proc)
27
+ end
28
+ end
@@ -0,0 +1,3 @@
1
+ Dir["#{File.dirname(__FILE__)}/testing_support/factories/**"].each do |f|
2
+ load File.expand_path(f)
3
+ end
@@ -0,0 +1,7 @@
1
+ FactoryBot.define do
2
+ factory :google_analytics_integration, class: Spree::Integrations::GoogleAnalytics do
3
+ active { true }
4
+ preferred_measurement_id { FFaker::Internet.password }
5
+ store { Spree::Store.default }
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module SpreeGoogleAnalytics
2
+ VERSION = '1.0.0'.freeze
3
+
4
+ def gem_version
5
+ Gem::Version.new(VERSION)
6
+ end
7
+ end
@@ -0,0 +1,5 @@
1
+ require 'spree_core'
2
+ require 'spree_extension'
3
+ require 'spree_google_analytics/engine'
4
+ require 'spree_google_analytics/version'
5
+ require 'spree_google_analytics/configuration'
metadata ADDED
@@ -0,0 +1,130 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: spree_google_analytics
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Vendo Connect Inc.
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2025-05-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: spree
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 5.1.0.beta
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 5.1.0.beta
27
+ - !ruby/object:Gem::Dependency
28
+ name: spree_storefront
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 5.1.0.beta
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 5.1.0.beta
41
+ - !ruby/object:Gem::Dependency
42
+ name: spree_admin
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 5.1.0.beta
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: 5.1.0.beta
55
+ - !ruby/object:Gem::Dependency
56
+ name: spree_extension
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description:
70
+ email: hello@spreecommerce.org
71
+ executables: []
72
+ extensions: []
73
+ extra_rdoc_files: []
74
+ files:
75
+ - LICENSE.md
76
+ - README.md
77
+ - Rakefile
78
+ - app/assets/config/spree_google_analytics_manifest.js
79
+ - app/assets/images/integration_icons/google-analytics-logo.png
80
+ - app/controllers/spree_google_analytics/store_controller_decorator.rb
81
+ - app/helpers/spree_google_analytics/base_helper.rb
82
+ - app/models/spree/integrations/google_analytics.rb
83
+ - app/presenters/spree_google_analytics/checkout_presenter.rb
84
+ - app/presenters/spree_google_analytics/order_presenter.rb
85
+ - app/presenters/spree_google_analytics/payment_presenter.rb
86
+ - app/presenters/spree_google_analytics/product_presenter.rb
87
+ - app/views/spree/admin/integrations/forms/_google_analytics.html.erb
88
+ - app/views/spree_google_analytics/_add_to_cart.html.erb
89
+ - app/views/spree_google_analytics/_add_to_wishlist.erb
90
+ - app/views/spree_google_analytics/_body_end.html.erb
91
+ - app/views/spree_google_analytics/_cart.html.erb
92
+ - app/views/spree_google_analytics/_checkout_complete.html.erb
93
+ - app/views/spree_google_analytics/_head.html.erb
94
+ - app/views/spree_google_analytics/_product.html.erb
95
+ - app/views/spree_google_analytics/_remove_from_cart.html.erb
96
+ - config/initializers/spree.rb
97
+ - config/locales/en.yml
98
+ - config/routes.rb
99
+ - lib/generators/spree_google_analytics/install/install_generator.rb
100
+ - lib/spree_google_analytics.rb
101
+ - lib/spree_google_analytics/configuration.rb
102
+ - lib/spree_google_analytics/engine.rb
103
+ - lib/spree_google_analytics/factories.rb
104
+ - lib/spree_google_analytics/testing_support/factories/google_analytics_integration.rb
105
+ - lib/spree_google_analytics/version.rb
106
+ homepage: https://github.com/spree/spree_google_analytics
107
+ licenses:
108
+ - AGPL-3.0-or-later
109
+ metadata: {}
110
+ post_install_message:
111
+ rdoc_options: []
112
+ require_paths:
113
+ - lib
114
+ required_ruby_version: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ version: '3.0'
119
+ required_rubygems_version: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ version: '0'
124
+ requirements:
125
+ - none
126
+ rubygems_version: 3.5.3
127
+ signing_key:
128
+ specification_version: 4
129
+ summary: Spree Commerce Google analytics Extension
130
+ test_files: []