Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update is coming ? Google Analytics 4 GA4 Killed my groove #159

Open
v2lrf opened this issue Mar 9, 2021 · 11 comments
Open

Update is coming ? Google Analytics 4 GA4 Killed my groove #159

v2lrf opened this issue Mar 9, 2021 · 11 comments

Comments

@v2lrf
Copy link

v2lrf commented Mar 9, 2021

An update is coming to deal with Google Analytics 4 (GA4), or should I wonder why I need to use old google pixel from old projects (GA3) to make rack-tracker work properly?

At this point, the issue is not really clear.
It's clear for instance that the javascript render injected inside the header does not fit for GA4 and makes some problems for the real-time console.

My investigation starts, but the only thing I can see is that with GA3 all is running perfectly... and with GA4 well there is something new behind that stuff...

Here the thing, GA4 ask some different patterns and I'm just wondering if it's not a good idea to care on old GA pixel and keep them alive for now :)

Actually, I don't know yet if anyone would be interested in it or fork it to upgrade my own?
Let me know if updating the gem is something open ;-)

If some of you encountered that issue let us know and if there is a better way to fix it fine

care

my setup

#gemfile
ruby "3.0.0"
gem "rails", "~> 6.1.3"
gem "rack-tracker" ,"~>1.12.1"
#...

I'll update that issue asap I got some info

@bumi
Copy link
Contributor

bumi commented Mar 10, 2021

not sure if I can follow. but PRs are very welcome! :)

@v2lrf
Copy link
Author

v2lrf commented Mar 10, 2021

not sure if I can follow. but PRs are very welcome! :)

ok thanks I ll see what I can do or propose

@bumi
Copy link
Contributor

bumi commented Mar 10, 2021

ok, keep me posted and let me know if you need help with the code

@puneetpandey
Copy link

puneetpandey commented Sep 18, 2022

Following up on this one.. any fix for GA4 released so far? @v2lrf

@puneetpandey
Copy link

I am somehow able to monkey patch the library and modified the code to meet with our requirements. Here's what I did:

  1. Created a new file under config/initializers/rack/tracker/handler.rb with:
class Rack::Tracker::Handler
  def render
    if handler_name == "google_analytics"
      Tilt.new(File.join(File.dirname(__FILE__), "#{handler_name}/template/#{handler_name}.erb")).render(self)
    end
  end
end
  1. Created a new file under config/initializers/rack/tracker/google_analytics/template/google_analytics.erb with:
<% if tracker %>
  <!-- Global site tag (gtag.js) - Google AdWords - Google Analytics 4 -->
  <script async src="https://www.googletagmanager.com/gtag/js?id=<%= tracker %>"></script>
  <script>
    window.dataLayer = window.dataLayer || [];
    function gtag(){dataLayer.push(arguments);}
    gtag('js', new Date());

    gtag('config', "<%= tracker %>");
  </script>
  <!-- End Global site tag (gtag.js) - Google AdWords -->

  <script type="text/javascript">
    <% events.each do |var| %>
      <% if var.category == "sign_up" %>
        gtag('event', "<%= var.category %>", {
          method: "<%= var.action %>"
        });
      <% else %>
        gtag('event', "<%= var.category %>", {
          action: "<%= var.action %>"
        });
      <% end %>
    <% end %>
  </script>
<% end %>
  1. Inside config/application.rb:
config.middleware.use(Rack::Tracker) do
  handler :google_analytics, { tracker: Rails.application.credentials.google_analytics_4_id, explicit_pageview: false }
end

Call to tracker remains the same, in my case sample call to sign_up is:

tracker do |t|
  t.google_analytics :send, { type: 'event', category: 'sign_up', action: 'Email', label: request_label }
end

I will see if I can cleanup the google_analytics.rb so that changes in erb would be simple to integrate without any if-else condition. But this is the working sample so far I have with GA4

@bumi
Copy link
Contributor

bumi commented Sep 29, 2022

do you want to put this in a PR?

@puneetpandey
Copy link

@bumi File: ../rack/tracker/google_analytics/google_analytics.rb need some changes before I raise a PR because all those Ecommerce classes and stuff are no longer required in GA4 or what I can do is to add new google_analytics_4 class and helper to call that function like: t.google_analytics_4 this way both the integrations remain active. Thoughts?

@DonSchado
Copy link
Collaborator

yes some type of versioning sounds reasonable :)

@ArtemBon
Copy link

@puneetpandey Hi! Have you worked on the PR?

@puneetpandey
Copy link

@ArtemBon The work is still in progress and I am yet to write some test cases around it. I am unable to take time out for this, so I appreciate any help you and/or others can provide

@puneetpandey
Copy link

Update: I am somehow unable to work on the new changeset but I have come up with another solution for this.

This gem is very flexible and allows me to create my own middleware tracker. So I created one like this:

inside lib folder I created google_analytics4_handler.rb

class GoogleAnalytics4Handler < Rack::Tracker::Handler
  self.allowed_tracker_options = [:cookie_domain, :user_id]

  def initialize(env, options = {})
    super(env, options)
  end

  class Send < OpenStruct
    def initialize(attrs = {})
      attrs.reverse_merge!(type: 'event')
      super
    end

    def write
      ['send', event].to_json.gsub(/\[|\]/, '')
    end

    def event
      { hitType: self.type }.merge(attributes.stringify_values).compact
    end

    def attributes
      Hash[to_h.slice(:category, :action, :label, :value).map { |k,v| [self.type.to_s + k.to_s.capitalize, v] }]
    end
  end

  class Parameter < OpenStruct
    include Rack::Tracker::JavaScriptHelper
    def write
      ['set', self.to_h.to_a].flatten.map { |v| %Q{'#{j(v)}'} }.join ', '
    end
  end

  def tracker
    options[:tracker].respond_to?(:call) ? options[:tracker].call(env) : options[:tracker]
  end

  def pageview_url_script
    options[:pageview_url_script] || 'window.location.pathname + window.location.search'
  end

  def render
    Tilt.new( File.join( File.dirname(__FILE__), 'templates', 'ga4_handler.erb') ).render(self)
  end

  private

  def tracker_option_key(key)
    key.to_s.camelize(:lower).to_sym
  end

  def tracker_option_value(value)
    value.to_s
  end
end

and created ga4_handler.erb inside lib/templates:

<!-- Global site tag (gtag.js) - Google Analytics 4 -->
<!--
<script async src="https://www.googletagmanager.com/gtag/js?id=<%#= tracker %>"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());

  gtag('config', "<%#= tracker %>");
</script>
-->
<!-- End Global site tag (gtag.js) - Google Analytics 4 -->
<% if tracker %>
  <script type="text/javascript">
    if(typeof gtag !== "undefined" && typeof gtag === "function") {
      <% events.each do |var| %>
        gtag('event', "<%= var.category %>", {
          method: "<%= var.action %>"
        });
      <% end %>
    } else {
      <% unless Rails.env.development? %>
        console.log("undefined gtag");
      <% end %>
    }
  </script>
<% end %>

I am initialising this in application.rb like this:

config.middleware.use(Rack::Tracker) do
  handler GoogleAnalytics4Handler, { tracker: Rails.application.credentials.ad_google_analytics_4_id }
end

and a call to this is like:

tracker do |t|
  t.google_analytics4_handler :send, { type: 'event', category: 'login', action: "Login Link" , label: nil }
end

P.S.: The reason I commented GA4 base tag is because I have already defined / included this base tag in my layout file. and this was resulting in duplicate GA4 tags as per Google Tag Assistant Legacy extension.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants