Skip to content

Commit

Permalink
Google Analytics version 4 snippet.
Browse files Browse the repository at this point in the history
  • Loading branch information
Thomas Scherz committed Jun 28, 2023
1 parent 96ce61e commit dca3ee9
Show file tree
Hide file tree
Showing 19 changed files with 1,279 additions and 12 deletions.
125 changes: 125 additions & 0 deletions app/assets/javascripts/hyrax/analytics_events.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
class TrackingTags {
constructor(provider) {
this.provider = provider
switch(this.provider) {
case 'matomo':
this.tracker = new MatomoTagTracker();
break;
case 'google':
this.tracker = new UATagTracker();
break;
case 'ga4':
this.tracker = new GA4TagTracker();
break;
default:
console.error('Unsupport analytics provider ' + this.provider + ', supported values are: matomo, google, ga4');
}
}

// Track an event with the configured provider
trackTagEvent(category, action, name) {
this.tracker.trackEvent(category, action, name);
}

// Track a page view with the configured provider
trackPageView() {
this.tracker.trackPageView();
}

// Deprecated: use trackTagEvent and trackPageView instead.
analytics() {
return this;
}

// Deprecated: use trackTagEvent and trackPageView instead.
push(params) {
if (params[0] == 'trackPageView' || params[0] == '_trackPageView') {
this.tracker.trackPageView();
} else {
this.tracker.trackTagEvent(params[1], params[2], params[3]);
}
}

// Deprecated
pageView() {
return 'trackPageView';
}

// Deprecated
trackEvent() {
return 'trackEvent';
}
}

class GA4TagTracker {
trackEvent(category, action, name) {
gtag('event', action, {
'category': category,
'label': name
});
}

trackPageView() {
// No operation necessary, this event is automatically collected
}
}

class UATagTracker {
trackEvent(category, action, name) {
_gaq.push(['_trackEvent', category, action, name]);
}

trackPageView() {
_gaq.push(['_trackPageView']);
}
}

class MatomoTagTracker {
trackEvent(category, action, name) {
_paq.push(['trackEvent', category, action, name]);
}

trackPageView() {
_paq.push(['trackPageView']);
}
}

function trackPageView() {
window.trackingTags.trackPageView();
}

function trackAnalyticsEvents() {
$('span.analytics-event').each(function(){
var eventSpan = $(this);
window.trackingTags.trackTagEvent(eventSpan.data('category'), eventSpan.data('action'), eventSpan.data('name'));
})
}

function setupTracking() {
var provider = $('meta[name="analytics-provider"]').prop('content')
if (provider === undefined) {
return;
}
window.trackingTags = new TrackingTags(provider);
trackPageView();
trackAnalyticsEvents();
}

if (typeof Turbolinks !== 'undefined') {
$(document).on('turbolinks:load', function() {
setupTracking();
});
} else {
$(document).on('ready', function() {
setupTracking();
});
}

$(document).on('click', '#file_download', function(e) {
window.trackingTags.trackTagEvent('file-set', 'file-set-download', $(this).data('label'));
window.trackingTags.trackTagEvent('file-set-in-work', 'file-set-in-work-download', $(this).data('work-id'));
$(this).data('collection-ids').forEach(function (collection) {
window.trackingTags.trackTagEvent('file-set-in-collection', 'file-set-in-collection-download', collection);
window.trackingTags.trackTagEvent('work-in-collection', 'work-in-collection-download', collection);
});
});
61 changes: 61 additions & 0 deletions app/controllers/hyrax/admin/collection_reports_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# frozen_string_literal: true
module Hyrax
module Admin
module Analytics
class CollectionReportsController < AnalyticsController
include Hyrax::BreadcrumbsForCollectionAnalytics
def index
return unless Hyrax.config.analytics? && Hyrax.config.analytics_provider != 'ga4'

@pageviews = Hyrax::Analytics.daily_events('collection-page-view')
@work_page_views = Hyrax::Analytics.daily_events('work-in-collection-view')
@downloads = Hyrax::Analytics.daily_events('work-in-collection-download')
@all_top_collections = Hyrax::Analytics.top_events('work-in-collection-view', date_range)
@top_collections = paginate(@all_top_collections, rows: 10)
@top_downloads = Hyrax::Analytics.top_events('work-in-collection-download', date_range)
@top_collection_pages = Hyrax::Analytics.top_events('collection-page-view', date_range)
respond_to do |format|
format.html
format.csv { export_data }
end
end

def show
return unless Hyrax.config.analytics? && Hyrax.config.analytics_provider != 'ga4'
@document = ::SolrDocument.find(params[:id])
@pageviews = Hyrax::Analytics.daily_events_for_id(@document.id, 'collection-page-view')
@work_page_views = Hyrax::Analytics.daily_events_for_id(@document.id, 'work-in-collection-view')
@uniques = Hyrax::Analytics.unique_visitors_for_id(@document.id)
@downloads = Hyrax::Analytics.daily_events_for_id(@document.id, 'work-in-collection-download')
respond_to do |format|
format.html
format.csv { export_data }
end
end

private

# rubocop:disable Metrics/MethodLength
def export_data
csv_row = CSV.generate do |csv|
csv << ["Name", "ID", "View of Works In Collection", "Downloads of Works In Collection", "Collection Page Views"]
@all_top_collections.each do |collection|
document = begin
::SolrDocument.find(collection[0])
rescue
"Collection deleted"
end
download_match = @top_downloads.detect { |a, _b| a == collection[0] }
download_count = download_match ? download_match[1] : 0
collection_match = @top_collection_pages.detect { |a, _b| a == collection[0] }
collection_count = collection_match ? collection_match[1] : 0
csv << [document, collection[0], collection[1], download_count, collection_count]
end
end
send_data csv_row, filename: "#{@start_date}-#{@end_date}-collections.csv"
end
# rubocop:enable Metrics/MethodLength
end
end
end
end
122 changes: 122 additions & 0 deletions app/controllers/hyrax/admin/work_reports_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
# frozen_string_literal: true
module Hyrax
module Admin
module Analytics
class WorkReportsController < AnalyticsController
include Hyrax::BreadcrumbsForWorksAnalytics

def index
return unless Hyrax.config.analytics? && Hyrax.config.analytics_provider != 'ga4'

@accessible_works ||= accessible_works
@accessible_file_sets ||= accessible_file_sets
@works_count = @accessible_works.count
@top_works = paginate(top_works_list, rows: 10)
@top_file_set_downloads = paginate(top_files_list, rows: 10)

if current_user.ability.admin?
@pageviews = Hyrax::Analytics.daily_events('work-view')
@downloads = Hyrax::Analytics.daily_events('file-set-download')
end

respond_to do |format|
format.html
format.csv { export_data }
end
end

def show
@pageviews = Hyrax::Analytics.daily_events_for_id(@document.id, 'work-view')
@uniques = Hyrax::Analytics.unique_visitors_for_id(@document.id)
@downloads = Hyrax::Analytics.daily_events_for_id(@document.id, 'file_set_in_work_download')
@files = paginate(@document._source["file_set_ids_ssim"], rows: 5)
respond_to do |format|
format.html
format.csv { export_data }
end
end

private

def accessible_works
models = Hyrax.config.curation_concerns.map { |m| "\"#{m}\"" }
if current_user.ability.admin?
ActiveFedora::SolrService.query("has_model_ssim:(#{models.join(' OR ')})",
fl: 'title_tesim, id, member_of_collections',
rows: 50_000)
else
ActiveFedora::SolrService.query(
"edit_access_person_ssim:#{current_user} AND has_model_ssim:(#{models.join(' OR ')})",
fl: 'title_tesim, id, member_of_collections',
rows: 50_000
)
end
end

def accessible_file_sets
if current_user.ability.admin?
ActiveFedora::SolrService.query(
"has_model_ssim:FileSet",
fl: 'title_tesim, id',
rows: 50_000
)
else
ActiveFedora::SolrService.query(
"edit_access_person_ssim:#{current_user} AND has_model_ssim:FileSet",
fl: 'title_tesim, id',
rows: 50_000
)
end
end

def top_analytics_works
@top_analytics_works ||= Hyrax::Analytics.top_events('work-view', date_range)
end

def top_analytics_downloads
@top_analytics_downloads ||= Hyrax::Analytics.top_events('file-set-in-work-download', date_range)
end

def top_analytics_file_sets
@top_analytics_file_sets ||= Hyrax::Analytics.top_events('file-set-download', date_range)
end

def top_works_list
list = []
top_analytics_works
top_analytics_downloads
@accessible_works.each do |doc|
views_match = @top_analytics_works.detect { |id, _count| id == doc["id"] }
@view_count = views_match ? views_match[1] : 0
downloads_match = @top_analytics_downloads.detect { |id, _count| id == doc["id"] }
@download_count = downloads_match ? downloads_match[1] : 0
list.push([doc["id"], doc["title_tesim"].join(''), @view_count, @download_count, doc["member_of_collections"]])
end
list.sort_by { |l| -l[2] }
end

def top_files_list
list = []
top_analytics_file_sets
@accessible_file_sets.each do |doc|
downloads_match = @top_analytics_file_sets.detect { |id, _count| id == doc["id"] }
@download_count = downloads_match ? downloads_match[1] : 0
list.push([doc["id"], doc["title_tesim"].join(''), @download_count]) if doc["title_tesim"].present?
end
list.sort_by { |l| -l[2] }
end

def export_data
data = top_works_list
csv_row = CSV.generate do |csv|
csv << ["Name", "ID", "Work Page Views", "Total Downloads of File Sets In Work", "Collections"]
data.each do |d|
csv << [d[0], d[1], d[2], d[3], d[4]]
end
end
send_data csv_row, filename: "#{params[:start_date]}-#{params[:end_date]}-works.csv"
end
end
end
end
end
Loading

0 comments on commit dca3ee9

Please sign in to comment.