Skip to content

Commit

Permalink
create google analytics 4 compatibility (#6815)
Browse files Browse the repository at this point in the history
* create google analytics 4 compatibility

* code cleanup

* call the cops

* go go gadget specs

---------

Co-authored-by: Daniel Pierce <dlpierce@indiana.edu>
  • Loading branch information
orangewolf and dlpierce committed May 24, 2024
1 parent 334d9ad commit 4d2c654
Show file tree
Hide file tree
Showing 30 changed files with 580 additions and 131 deletions.
2 changes: 2 additions & 0 deletions .dassie/Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ gem 'dalli'
gem 'devise'
gem 'devise-guests', '~> 0.8'
gemspec name: 'hyrax', path: ENV.fetch('HYRAX_ENGINE_PATH', '..')
gem 'google-protobuf', force_ruby_platform: true # required because google-protobuf is not compatible with Alpine linux
gem 'grpc', force_ruby_platform: true # required because google-protobuf is not compatible with Alpine linux
gem 'jbuilder', '~> 2.5'
gem 'jquery-rails'
gem 'pg', '~> 1.3'
Expand Down
7 changes: 6 additions & 1 deletion .dassie/config/analytics.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
analytics:
ga4:
analytics_id: <%= ENV['GOOGLE_ANALYTICS_ID'] %>
property_id: <%= ENV['GOOGLE_ANALYTICS_PROPERTY_ID'] %>
account_json: <%= ENV['GOOGLE_ACCOUNT_JSON'] %>
account_json_path: <%= ENV['GOOGLE_ACCOUNT_JSON_PATH'] %>
google:
analytics_id: <%= ENV['GOOGLE_ANALYTICS_ID'] %>
app_name: <%= ENV['GOOGLE_OAUTH_APP_NAME'] %>
app_version: <%= ENV['GOOGLE_OAUTH_APP_VERSION'] %>
privkey_value: <%= ENV['GOOGLE_OAUTH_PRIVATE_KEY_VALUE'] %>
privkey_path: <%= ENV['GOOGLE_OAUTH_PRIVATE_KEY_PATH'] %>
privkey_value: <%= ENV['GOOGLE_OAUTH_PRIVATE_KEY_VALUE'] %>
privkey_secret: <%= ENV['GOOGLE_OAUTH_PRIVATE_KEY_SECRET'] %>
client_email: <%= ENV['GOOGLE_OAUTH_CLIENT_EMAIL'] %>
matomo:
Expand Down
2 changes: 2 additions & 0 deletions .koppie/Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ gem 'coffee-rails', '~> 4.2'
gem 'dalli'
gem 'devise'
gem 'devise-guests', '~> 0.8'
gem 'google-protobuf', force_ruby_platform: true # required because google-protobuf is not compatible with Alpine linux
gem 'grpc', force_ruby_platform: true # required because google-protobuf is not compatible with Alpine linux
gemspec name: 'hyrax', path: ENV.fetch('HYRAX_ENGINE_PATH', '..')
gem 'jbuilder', '~> 2.5'
gem 'jquery-rails'
Expand Down
7 changes: 6 additions & 1 deletion .koppie/config/analytics.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
analytics:
ga4:
analytics_id: <%= ENV['GOOGLE_ANALYTICS_ID'] %>
property_id: <%= ENV['GOOGLE_ANALYTICS_PROPERTY_ID'] %>
account_json: <%= ENV['GOOGLE_ACCOUNT_JSON'] %>
account_json_path: <%= ENV['GOOGLE_ACCOUNT_JSON_PATH'] %>
google:
analytics_id: <%= ENV['GOOGLE_ANALYTICS_ID'] %>
app_name: <%= ENV['GOOGLE_OAUTH_APP_NAME'] %>
app_version: <%= ENV['GOOGLE_OAUTH_APP_VERSION'] %>
privkey_value: <%= ENV['GOOGLE_OAUTH_PRIVATE_KEY_VALUE'] %>
privkey_path: <%= ENV['GOOGLE_OAUTH_PRIVATE_KEY_PATH'] %>
privkey_value: <%= ENV['GOOGLE_OAUTH_PRIVATE_KEY_VALUE'] %>
privkey_secret: <%= ENV['GOOGLE_OAUTH_PRIVATE_KEY_SECRET'] %>
client_email: <%= ENV['GOOGLE_OAUTH_CLIENT_EMAIL'] %>
matomo:
Expand Down
70 changes: 47 additions & 23 deletions app/assets/javascripts/hyrax/analytics_events.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,39 +4,53 @@ class TrackingTags {
}

analytics() {
if(this.provider === "matomo") {
switch(this.provider) {
case "matomo":
return _paq;
}
else {
case "ga4":
return dataLayer;
default:
return _gaq;
}
}

pageView() {
if(this.provider === "matomo") {
return 'trackPageView'
} else {
return '_trackPageview'
switch(this.provider) {
case "matomo":
return 'trackPageView';
case "ga4":
return 'event';
default:
return '_trackPageview';
}
}

trackEvent() {
if(this.provider === "matomo") {
return 'trackEvent'
} else {
return '_trackEvent'
switch(this.provider) {
case "matomo":
return 'trackEvent';
case "ga4":
return 'event';
default:
return '_trackEvent';
}
}
}

function trackPageView() {
window.trackingTags.analytics().push([window.trackingTags.pageView()]);
function trackPageView(provider) {
if(provider !== 'ga4'){
window.trackingTags.analytics().push([window.trackingTags.pageView()]);
}
}

function trackAnalyticsEvents() {
function trackAnalyticsEvents(provider) {
$('span.analytics-event').each(function(){
var eventSpan = $(this)
window.trackingTags.analytics().push([window.trackingTags.trackEvent(), eventSpan.data('category'), eventSpan.data('action'), eventSpan.data('name')]);
if(provider !== 'ga4') {
window.trackingTags.analytics().push([window.trackingTags.trackEvent(), eventSpan.data('category'), eventSpan.data('action'), eventSpan.data('name')]);
} else {
gtag('event', eventspan.data('action'), { 'content_type': eventspan.data('category'), 'content_id': eventspan.data('name')})
}
})
}

Expand All @@ -46,8 +60,8 @@ function setupTracking() {
return;
}
window.trackingTags = new TrackingTags(provider)
trackPageView()
trackAnalyticsEvents()
trackPageView(provider)
trackAnalyticsEvents(provider)
}

if (typeof Turbolinks !== 'undefined') {
Expand All @@ -66,10 +80,20 @@ $(document).on('click', '#file_download', function(e) {
return;
}
window.trackingTags = new TrackingTags(provider)
window.trackingTags.analytics().push([trackingTags.trackEvent(), 'file-set', 'file-set-download', $(this).data('label')]);
window.trackingTags.analytics().push([trackingTags.trackEvent(), 'file-set-in-work', 'file-set-in-work-download', $(this).data('work-id')]);
$(this).data('collection-ids').forEach(function (collection) {
window.trackingTags.analytics().push([trackingTags.trackEvent(), 'file-set-in-collection', 'file-set-in-collection-download', collection]);
window.trackingTags.analytics().push([trackingTags.trackEvent(), 'work-in-collection', 'work-in-collection-download', collection]);
});

if(provider !== 'ga4') {
window.trackingTags.analytics().push([trackingTags.trackEvent(), 'file-set', 'file-set-download', $(this).data('label')]);
window.trackingTags.analytics().push([trackingTags.trackEvent(), 'file-set-in-work', 'file-set-in-work-download', $(this).data('work-id')]);
$(this).data('collection-ids').forEach(function (collection) {
window.trackingTags.analytics().push([trackingTags.trackEvent(), 'file-set-in-collection', 'file-set-in-collection-download', collection]);
window.trackingTags.analytics().push([trackingTags.trackEvent(), 'work-in-collection', 'work-in-collection-download', collection]);
});
} else {
gtag('event', 'file-set-download', { 'content-type': 'file-set', 'content-id': $(this).data('label')})
gtag('event', 'file-set-in-work-download', { 'content-type': 'file-set-in-work', 'content-id': $(this).data('work-id')})
$(this).data('collection-ids').forEach(function (collection) {
gtag('event', 'file-set-in-collection-download', { 'content-type': 'file-set-in-collection', 'content-id': collection })
gtag('event', 'work-in-collection-download', { 'content-type': 'work-in-collection', 'content-id': collection })
});
}
});
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,17 @@ module SingularSubresourceController

included do
before_action :find_work, only: :work
before_action :find_file_set, only: :file
load_and_authorize_resource :work, only: :work
load_and_authorize_resource :file, class: 'FileSet', only: :file, id_param: :id
load_and_authorize_resource :file, only: :file
end

def find_work
@work = Hyrax::WorkRelation.new.find(params[:id])
@work = Hyrax.query_service.find_by(id: params[:id])
end

def find_file_set
@file = Hyrax.query_service.find_by(id: params[:id])
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def show
private

def accessible_works
models = Hyrax.config.curation_concerns.map { |m| "\"#{m}\"" }
models = Hyrax::ModelRegistry.work_rdf_representations.map { |m| "\"#{m}\"" }
if current_user.ability.admin?
Hyrax::SolrService.query("has_model_ssim:(#{models.join(' OR ')})",
fl: 'title_tesim, id, member_of_collections',
Expand All @@ -54,15 +54,16 @@ def accessible_works
end

def accessible_file_sets
file_set_model_clause = "has_model_ssim:\"#{Hyrax::ModelRegistry.file_set_rdf_representations.join('" OR "')}\""
if current_user.ability.admin?
Hyrax::SolrService.query(
"has_model_ssim:FileSet",
file_set_model_clause,
fl: 'title_tesim, id',
rows: 50_000
)
else
Hyrax::SolrService.query(
"edit_access_person_ssim:#{current_user} AND has_model_ssim:FileSet",
"edit_access_person_ssim:#{current_user} AND #{file_set_model_clause}",
fl: 'title_tesim, id',
rows: 50_000
)
Expand Down
2 changes: 1 addition & 1 deletion app/models/file_download_stat.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def ga_statistics(start_date, file)

# this is called by the parent class
def filter(file)
{ file_id: file.id }
{ file_id: file.id.to_s }
end
end
end
2 changes: 1 addition & 1 deletion app/models/file_view_stat.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ class FileViewStat < Hyrax::Statistic
class << self
# this is called by the parent class
def filter(file)
{ file_id: file.id }
{ file_id: file.id.to_s }
end
end
end
22 changes: 3 additions & 19 deletions app/models/hyrax/statistic.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,22 +25,6 @@ def statistics(object, start_date, user_id = nil)
combined_stats object, start_date, cache_column, event_type, user_id
end

# Hyrax::Download is sent to Hyrax::Analytics.profile as #hyrax__download
# see Legato::ProfileMethods.method_name_from_klass
def ga_statistics(start_date, object)
path = polymorphic_path(object)
profile = Hyrax::Analytics.profile
unless profile
Hyrax.logger.error("Google Analytics profile has not been established. Unable to fetch statistics.")
return []
end
profile.hyrax__pageview(sort: 'date',
start_date: start_date,
end_date: Date.yesterday,
limit: 10_000)
.for_path(path)
end

def query_works(query)
models = Hyrax.config.curation_concerns.map { |m| "\"#{m}\"" }
Hyrax::SolrService.query("has_model_ssim:(#{models.join(' OR ')})", fl: query, rows: 100_000)
Expand Down Expand Up @@ -80,10 +64,10 @@ def combined_stats(object, start_date, object_method, ga_key, user_id = nil)
stat_cache_info = cached_stats(object, start_date, object_method)
stats = stat_cache_info[:cached_stats]
if stat_cache_info[:ga_start_date] < Time.zone.today
ga_stats = ga_statistics(stat_cache_info[:ga_start_date], object)
ga_stats.each do |stat|
page_stats = Hyrax::Analytics.page_statistics(stat_cache_info[:ga_start_date], object)
page_stats.each do |stat|
lstat = build_for(object, date: stat[:date], object_method => stat[ga_key], user_id: user_id)
lstat.save unless Date.parse(stat[:date]) == Time.zone.today
lstat.save unless stat[:date].to_date == Time.zone.today
stats << lstat
end
end
Expand Down
2 changes: 1 addition & 1 deletion app/presenters/hyrax/file_usage.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ module Hyrax
# and prepares it for visualization in /app/views/stats/file.html.erb
class FileUsage < StatsUsagePresenter
def initialize(id)
self.model = ::FileSet.find(id)
self.model = Hyrax.query_service.find_by(id: id)
end

alias file model
Expand Down
1 change: 1 addition & 0 deletions app/presenters/hyrax/stats_usage_presenter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ def date_for_analytics
end

def string_to_date(date_str)
return date_str if date_str.is_a?(Date)
Time.zone.parse(date_str)
rescue ArgumentError, TypeError
nil
Expand Down
Loading

0 comments on commit 4d2c654

Please sign in to comment.