ga_trackable 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: dc165dc8d86aa90d10356dfe90e2bc982974443c
4
+ data.tar.gz: f89011a9ea3777d70aa4ca2f1b2f3e6ae2d6c106
5
+ SHA512:
6
+ metadata.gz: e1bcc38ff487a2823cbdd53447080b9a86a56fbe5eb8ffd4e56ef0362594fcfe0849da05d4b093b21e22b7f3eafb8bc9bf421c2c78d1e1caf4b0d6c540dbebc9
7
+ data.tar.gz: 0c7b4ce17aa26ed516668c263ba7b880309bf513aadf2618810bb4534dac3fab52dfae221deaa0db11ece98d293c40e35bad48948b4de400eaef711035df11e9
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2016 HttpLab
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1 @@
1
+ # ga_trackable
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+ require 'bundler/gem_tasks'
3
+
4
+ task :console do
5
+ require 'pry'
6
+ lib = File.expand_path('lib')
7
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
8
+ require 'ga_trackable'
9
+ ARGV.clear
10
+ Pry.start
11
+ end
@@ -0,0 +1,91 @@
1
+ # frozen_string_literal: true
2
+ class GaTrackable::BaseFetcher
3
+
4
+ GA_DATE_FORMAT = '%Y-%m-%d'
5
+
6
+ attr_reader :start_date
7
+ attr_reader :end_date
8
+ attr_accessor :sometime_processed_counters
9
+
10
+ def initialize(
11
+ client: GaTrackable.client,
12
+ analytics: GaTrackable.analytics,
13
+ config: GaTrackable.config
14
+ )
15
+ @client = client
16
+ @analytics = analytics
17
+ @config = config
18
+ @sometime_processed_counters = []
19
+ end
20
+
21
+ # Вытащить просмотры за текущий день. Метод может вызываться много раз,
22
+ # количество просмотров за текущий день будет обновляться.
23
+ def fetch_for_current_day!
24
+ @start_date = DateTime.current.beginning_of_day
25
+ @end_date = DateTime.current
26
+
27
+ self.sometime_processed_counters = []
28
+
29
+ start_index = 1
30
+ max_results = 1000
31
+
32
+ begin
33
+ rows = get_data(start_date, end_date, start_index, max_results).rows
34
+ rows.each do |row|
35
+ begin
36
+ process_row(row, create_in_past: true)
37
+ rescue => ex
38
+ handle_exception(ex)
39
+ end
40
+ end
41
+ start_index += max_results
42
+ end while rows.size == max_results
43
+
44
+ self.sometime_processed_counters = []
45
+ true
46
+ end
47
+
48
+ private
49
+
50
+ # Инициализировать кеши просмотров. Метод приватный, потому что его вызов
51
+ # приведет к тому, что все каунтеры будут удалены и перестроены.
52
+ # Стартовой датой считаем 1 год назад.
53
+ # Вытаскиваем просмотры за все время, исключая сегодняшний день.
54
+ # Просмотры за сегодня и далее должны вытаскиваться с помощью fetch_for_current_day! и
55
+ # запоминаться в виде отдельного счетчика.
56
+ def initial_fetch!(start_date: 1.year.ago)
57
+ @start_date = start_date
58
+ @end_date = 1.day.ago.end_of_day
59
+
60
+ self.sometime_processed_counters = []
61
+ counter_class.delete_all
62
+
63
+ start_index = 1
64
+ max_results = 1000
65
+
66
+ begin
67
+ rows = get_data(start_date, end_date, start_index, max_results).rows
68
+ rows.each do |row|
69
+ begin
70
+ process_row(row, create_in_past: true)
71
+ rescue => ex
72
+ handle_exception(ex)
73
+ end
74
+ end
75
+ start_index += max_results
76
+ end while rows.size == max_results
77
+
78
+ self.sometime_processed_counters = []
79
+ true
80
+ end
81
+
82
+ def handle_exception(ex)
83
+ @config.out << "Exception occured:\n"
84
+ @config.out << ex.message
85
+ @config.out << "\n"
86
+ @config.out << ex.backtrace.join("\n")
87
+
88
+ @config.exceptions_handler.error(ex)
89
+ end
90
+
91
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+ require 'active_model'
3
+
4
+ module GaTrackable
5
+ class Configuration
6
+
7
+ include ActiveModel::Validations
8
+
9
+ def self.attribute_names
10
+ %i(app_name app_version secret_path secret_key scope issuer_email view_id page_views_black_filter page_views_white_filter page_views_entity_fetcher video_plays_entity_fetcher out exceptions_handler video_url_base rails_env)
11
+ end
12
+
13
+ def attribute_names
14
+ self.class.attribute_names
15
+ end
16
+
17
+ attr_accessor *attribute_names
18
+
19
+ validates(
20
+ :app_name,
21
+ :app_version,
22
+ :secret_path,
23
+ :secret_key,
24
+ :scope,
25
+ :issuer_email,
26
+ :view_id,
27
+ :page_views_white_filter,
28
+ :out,
29
+ presence: true
30
+ )
31
+
32
+ def initialize
33
+ @view_id = ENV['GA_TRACKABLE_VIEW_ID']
34
+ @app_name = ENV['GA_TRACKABLE_APP_NAME']
35
+ @app_version = ENV['GA_TRACKABLE_APP_VERSION']
36
+ @secret_path = ENV['GA_TRACKABLE_SECRET_PATH']
37
+ @secret_key = ENV['GA_TRACKABLE_KEY_SECRET']
38
+ @scope = ENV['GA_TRACKABLE_SCOPE']
39
+ @issuer_email = ENV['GA_TRACKABLE_ISSUER_EMAIL']
40
+ @page_views_white_filter = ENV['GA_TRACKABLE_PAGEVIEWS_WHITE_FILTER']
41
+ @page_views_black_filter = ENV['GA_TRACKABLE_PAGEVIEWS_BLACK_FILTER']
42
+ @out = STDOUT
43
+ @video_url_base = []
44
+
45
+ yield(self) if block_given?
46
+
47
+ [
48
+ @view_id,
49
+ @app_name,
50
+ @app_version,
51
+ @secret_path,
52
+ @secret_key,
53
+ @scope,
54
+ @issuer_email,
55
+ @page_views_white_filter,
56
+ @page_views_black_filter
57
+ ].each(&:freeze)
58
+ end
59
+
60
+ end
61
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+ module GaTrackable
3
+ class Engine < ::Rails::Engine
4
+
5
+ isolate_namespace GaTrackable
6
+
7
+ rake_tasks do
8
+ Dir[File.join(File.dirname(__FILE__), 'tasks/*.rake')].each {|f| load f }
9
+ end
10
+
11
+ end
12
+ end
@@ -0,0 +1,102 @@
1
+ # frozen_string_literal: true
2
+ class GaTrackable::PageViewsFetcher < GaTrackable::BaseFetcher
3
+
4
+ def counter_class
5
+ GaTrackable::PageViewsCounter
6
+ end
7
+
8
+ # Поулчить данные по просмотрам для конкретного пути. Используется в rake-таске.
9
+ def get_details_for(start_date: 1.year.ago, path:)
10
+ ga_start_date = start_date.strftime(GA_DATE_FORMAT)
11
+ ga_end_date = DateTime.current.strftime(GA_DATE_FORMAT)
12
+
13
+ data = @client.execute(api_method: @analytics.data.ga.get, parameters: {
14
+ 'ids' => "ga:#{@config.view_id}",
15
+ 'start-date' => ga_start_date,
16
+ 'end-date' => ga_end_date,
17
+ 'dimensions' => 'ga:pagePath,ga:pageTitle',
18
+ 'metrics' => 'ga:uniquePageviews,ga:pageviews',
19
+ 'sort' => 'ga:pagePath,ga:pageTitle',
20
+ 'filters' => "ga:pagePath=@#{path}"
21
+ }).data
22
+ end
23
+
24
+ private
25
+
26
+ # Обработать запись из коллекции, которую отдает гуглоаналитика.
27
+ # create_in_past нужен для создания счетчика "вчера". Это нужно в случае стартовой инициализации счетчиков.
28
+ # Стартовые данные за весь период записываем вчерашним днем, за сегодня и далее -- записываем стандартным образом.
29
+ def process_row(row, create_in_past: false)
30
+ # Пропускаем события с demo
31
+ return if @config.page_views_black_filter && row[0] =~ @config.page_views_black_filter
32
+ page_path = URI(row[0].split('?').first).path.chomp('/')
33
+ unique_page_views = row[1].to_i
34
+ page_views = row[2].to_i
35
+ entity = get_entity(page_path)
36
+
37
+ # Пытаемся получить каунтер на сегодняшний день.
38
+ today_counters = entity.page_views_counters.where('created_at >= ?', start_date)
39
+ fail "more than one today counter for #{entity.class.name}##{entity.id}" if today_counters.size > 1
40
+
41
+ if today_counters.any?
42
+ counter = today_counters.first
43
+ else
44
+ counter = entity.page_views_counters.build(page_path: page_path)
45
+ if create_in_past
46
+ counter.created_at = 1.day.ago
47
+ counter.updated_at = counter.created_at
48
+ counter.initial_data = true
49
+ end
50
+ end
51
+
52
+ # Аналитика считает просмотры по каждому url-у и тайтлу.
53
+ # Это значит что если в процессе существования сущности менялся ее тайтл,
54
+ # но не менялся url, аналитика отдаст столько записей, сколько было разных тайтлов.
55
+ # Нам нужна агрегированная информация по тайтлам. Для этого введен массив sometime_processed_counters
56
+ # Если url в нем есть, значит количество просмотров не инициализируем, а инкрементируем.
57
+ if sometime_processed_counters.index(page_path)
58
+ counter.unique_page_views += unique_page_views
59
+ counter.page_views += page_views
60
+ else
61
+ counter.unique_page_views = unique_page_views
62
+ sometime_processed_counters << page_path
63
+ counter.page_views = page_views
64
+ end
65
+
66
+ counter.save!
67
+ end
68
+
69
+ def get_data(tstart, tend, start_index, max_results)
70
+ ga_start_date = tstart.strftime(GA_DATE_FORMAT)
71
+ ga_end_date = tend.strftime(GA_DATE_FORMAT)
72
+
73
+ params = {
74
+ 'ids' => "ga:#{@config.view_id}",
75
+ 'start-date' => ga_start_date,
76
+ 'end-date' => ga_end_date,
77
+ 'start-index' => start_index,
78
+ 'max-results' => max_results,
79
+ 'dimensions' => 'ga:pagePath',
80
+ 'metrics' => 'ga:uniquePageviews,ga:pageviews',
81
+ 'sort' => 'ga:pagePath',
82
+ 'filters' => "ga:pagePath=~#{@config.page_views_white_filter}"
83
+ }
84
+
85
+ data = @client.execute(api_method: @analytics.data.ga.get, parameters: params).data
86
+
87
+ GaTrackable.out << "Page views data:\n"
88
+ GaTrackable.out << "params:\n"
89
+ GaTrackable.out << params.to_s
90
+ GaTrackable.out << "\n"
91
+ GaTrackable.out << "response:\n"
92
+ GaTrackable.out << data.rows.to_s
93
+ GaTrackable.out << "\n"
94
+
95
+ data
96
+ end
97
+
98
+ def get_entity(page_path)
99
+ @config.page_views_entity_fetcher.call(page_path)
100
+ end
101
+
102
+ end
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+ require 'colorize'
3
+
4
+ namespace :ga_trackable do
5
+ # Все таски ga должны зависеть от check_staging, для предотвращения запуска
6
+ # в стейджинг-окружении.
7
+ task check_staging: :environment do
8
+ if GaTrackable.config.rails_env && GaTrackable.config.rails_env.staging?
9
+ puts 'Запрещен запуск задач GA на стейджинг-сервере.'.red
10
+ exit
11
+ end
12
+ end
13
+
14
+ desc 'Обновить статистику просмотров за сегодняшний день'
15
+ task fetch_for_current_day: :check_staging do
16
+ if GaTrackable.config.page_views_entity_fetcher
17
+ GaTrackable::PageViewsFetcher.new.fetch_for_current_day!
18
+ end
19
+ if GaTrackable.config.video_plays_entity_fetcher
20
+ GaTrackable::VideoPlaysFetcher.new.fetch_for_current_day!
21
+ end
22
+ end
23
+
24
+ desc 'Initial fetch'
25
+ task initial_fetch: :check_staging do
26
+ if GaTrackable.config.page_views_entity_fetcher
27
+ GaTrackable::PageViewsFetcher.new.send(:initial_fetch!, start_date: 1.year.ago)
28
+ end
29
+ if GaTrackable.config.video_plays_entity_fetcher
30
+ GaTrackable::VideoPlaysFetcher.new.send(:initial_fetch!, start_date: 1.year.ago)
31
+ end
32
+ end
33
+
34
+ desc 'Отобразить детальную информацию по просмотрам страниц'
35
+ task get_details_for_page_views: :check_staging do
36
+ path = ENV['path']
37
+ unless path.present?
38
+ puts <<-HERE.strip_heredoc
39
+ Отобразить детальную информацию по просмотрам страниц:
40
+ rake uralok:ga:get_details_for_page_views path=/programs/home-concert1/stories/tomas-live start_date=2014-10-01
41
+ * Параметр start_date не обязателен (по-умолчанию: 1.year.ago).
42
+ HERE
43
+ exit
44
+ end
45
+
46
+ f = GaTrackable::PageViewsFetcher.new
47
+ opts = { path: path }
48
+ opts[:start_date] = DateTime.parse(ENV['start_date']) if ENV['start_date'].present?
49
+ data = f.get_details_for opts
50
+
51
+ totalUniquePageViews = 0
52
+ totalPageViews = 0
53
+ data.rows.each do |row|
54
+ puts [data.columnHeaders[0].name.rjust(18), row[0]].join(': ')
55
+ puts [data.columnHeaders[1].name.rjust(18), row[1]].join(': ')
56
+ puts [data.columnHeaders[2].name, row[2]].join(': ')
57
+ puts [data.columnHeaders[3].name, row[3]].join(': ')
58
+ totalUniquePageViews += row[2].to_i
59
+ totalPageViews += row[3].to_i
60
+ puts '---'
61
+ end
62
+
63
+ puts "Всего уникальных просмотров за выбранный период: #{totalUniquePageViews}".green
64
+ puts "Всего просмотров за выбранный период: #{totalPageViews}".green
65
+ end
66
+
67
+ desc 'Отобразить детальную информацию по просмотрам видео'
68
+ task get_details_for_video_plays: :check_staging do
69
+ path = ENV['path']
70
+ unless path.present?
71
+ puts <<-HERE.strip_heredoc
72
+ Отобразить детальную информацию по просмотрам видео:
73
+ rake uralok:ga:get_details_for_video_plays path=/programs/home-concert1/stories/tomas-live start_date=2014-10-01
74
+ * Параметр start_date не обязателен (по-умолчанию: 1.year.ago).
75
+ HERE
76
+ exit
77
+ end
78
+
79
+ f = GaTrackable::VideoPlaysFetcher.new
80
+ opts = { path: path }
81
+ opts[:start_date] = DateTime.parse(ENV['start_date']) if ENV['start_date'].present?
82
+ data = f.get_details_for opts
83
+
84
+ totalUniqueEvents = 0
85
+ totalEvents = 0
86
+ data.rows.each do |row|
87
+ puts [data.columnHeaders[0].name.rjust(18), row[0]].join(': ')
88
+ puts [data.columnHeaders[1].name.rjust(18), row[1]].join(': ')
89
+ puts [data.columnHeaders[2].name.rjust(18), row[2]].join(': ')
90
+ puts [data.columnHeaders[3].name.rjust(18), row[3]].join(': ')
91
+ puts [data.columnHeaders[4].name.rjust(18), row[4]].join(': ')
92
+ totalUniqueEvents += row[3].to_i
93
+ totalEvents += row[4].to_i
94
+ puts '---'
95
+ end
96
+
97
+ puts "Всего уникальных просмотров за выбранный период: #{totalUniqueEvents}".green
98
+ puts "Всего просмотров за выбранный период: #{totalEvents}".green
99
+ end
100
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+ module GaTrackable::Trackable
3
+ extend ActiveSupport::Concern
4
+
5
+ module ClassMethods
6
+ def ga_trackable(video_plays:)
7
+ setup_page_views_relations
8
+ setup_video_plays_relations if video_plays
9
+ end
10
+
11
+ def setup_page_views_relations
12
+ has_many :page_views_counters, class_name: GaTrackable::PageViewsCounter, as: :trackable, dependent: :destroy
13
+ include PageViewsMethods
14
+ end
15
+
16
+ def setup_video_plays_relations
17
+ has_many :video_plays_counters, class_name: GaTrackable::VideoPlaysCounter, as: :trackable, dependent: :destroy
18
+ include VideoPlaysMethods
19
+ end
20
+ end
21
+
22
+ module PageViewsMethods
23
+ extend ActiveSupport::Concern
24
+
25
+ def total_unique_page_views
26
+ page_views_counters.sum(:unique_page_views)
27
+ end
28
+
29
+ def total_page_views
30
+ page_views_counters.sum(:page_views)
31
+ end
32
+ end
33
+
34
+ module VideoPlaysMethods
35
+ extend ActiveSupport::Concern
36
+
37
+ def total_unique_video_plays
38
+ video_plays_counters.sum(:unique_events)
39
+ end
40
+
41
+ def total_video_plays
42
+ video_plays_counters.sum(:total_events)
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+ module GaTrackable
3
+ VERSION = '0.0.1'
4
+ end
@@ -0,0 +1,126 @@
1
+ # frozen_string_literal: true
2
+ class GaTrackable::VideoPlaysFetcher < GaTrackable::BaseFetcher
3
+
4
+ GA_FILTER = 'Video Plays'
5
+
6
+ def counter_class
7
+ GaTrackable::VideoPlaysCounter
8
+ end
9
+
10
+ # Поулчить данные по просмотрам для конкретного пути. Используется в rake-таске.
11
+ def get_details_for(start_date: 1.year.ago, path:)
12
+ ga_start_date = start_date.in_time_zone.strftime(GA_DATE_FORMAT)
13
+ ga_end_date = DateTime.current.strftime(GA_DATE_FORMAT)
14
+
15
+ data = @client.execute(api_method: @analytics.data.ga.get, parameters: {
16
+ 'ids' => "ga:#{@config.view_id}",
17
+ 'start-date' => ga_start_date,
18
+ 'end-date' => ga_end_date,
19
+ 'dimensions' => 'ga:eventCategory,ga:eventAction',
20
+ 'metrics' => 'ga:uniqueEvents,ga:totalEvents',
21
+ 'sort' => 'ga:eventCategory,ga:eventAction',
22
+ 'filters' => "ga:eventCategory==#{GA_FILTER};ga:eventAction=@#{path}"
23
+ }).data
24
+ end
25
+
26
+ private
27
+
28
+ # create_in_past нужен для создания счетчика "вчера". Это нужно в случае стартовой инициализации счетчиков.
29
+ # Стартовые данные за весь период записываем вчерашним днем, за сегодня и далее -- записываем стандартным образом.
30
+ # По-просмотрам видео есть специфика:
31
+ # одной странице могут соответствовать разные видеофайлы(event_action) в разное время.
32
+ def process_row(row, hsh = {})
33
+ event_action = row[1]
34
+
35
+ entities = get_entities(fetch_video_url(event_action))
36
+
37
+ entities.each {|e| process_entity(e, row, hsh) }
38
+ end
39
+
40
+ def process_entity(entity, row, create_in_past: false)
41
+ event_category = row[0]
42
+ event_action = row[1]
43
+ unique_events = row[2].to_i
44
+ total_events = row[3].to_i
45
+
46
+ # Пытаемся получить каунтер на сегодняшний день для полученного видеофайла (event_action).
47
+ today_counters = entity.video_plays_counters.where('created_at >= ? AND event_action = ?', start_date, event_action)
48
+ fail "more than one today counter for #{entity.class.name}##{entity.id} and <#{event_action}>" if today_counters.size > 1
49
+
50
+ if today_counters.any?
51
+ counter = today_counters.first
52
+ else
53
+ counter = entity.video_plays_counters.build(
54
+ event_category: event_category,
55
+ event_action: event_action
56
+ )
57
+ if create_in_past
58
+ counter.created_at = 1.day.ago
59
+ counter.updated_at = counter.created_at
60
+ counter.initial_data = true
61
+ end
62
+ end
63
+
64
+ # Мы считаем просмотры по event_action плейлист.
65
+ # В выдаче аналитики комбинации страница + видеофайл могут встречаться много раз.
66
+ # По этому код ниже определяет надо инициализировать счетчики, или инкрементировать.
67
+ key = event_action
68
+ if sometime_processed_counters.index(key)
69
+ counter.unique_events += unique_events
70
+ counter.total_events += total_events
71
+ else
72
+ counter.unique_events = unique_events
73
+ counter.total_events = total_events
74
+ sometime_processed_counters << key
75
+ end
76
+
77
+ counter.save!
78
+ end
79
+
80
+ def get_data(tstart, tend, start_index, max_results)
81
+ ga_start_date = tstart.strftime(GA_DATE_FORMAT)
82
+ ga_end_date = tend.strftime(GA_DATE_FORMAT)
83
+
84
+ params = {
85
+ 'ids' => "ga:#{@config.view_id}",
86
+ 'start-date' => ga_start_date,
87
+ 'end-date' => ga_end_date,
88
+ 'start-index' => start_index,
89
+ 'max-results' => max_results,
90
+ 'dimensions' => 'ga:eventCategory,ga:eventAction',
91
+ 'metrics' => 'ga:uniqueEvents,ga:totalEvents',
92
+ 'sort' => 'ga:eventCategory,ga:eventAction',
93
+ 'filters' => "ga:eventCategory==#{GA_FILTER}"
94
+ }
95
+ data = @client.execute(api_method: @analytics.data.ga.get, parameters: params).data
96
+
97
+ GaTrackable.out << "Video plays data:\n"
98
+ GaTrackable.out << "params:\n"
99
+ GaTrackable.out << params.to_s
100
+ GaTrackable.out << "\n"
101
+ GaTrackable.out << "response:\n"
102
+ GaTrackable.out << data.rows.to_s
103
+ GaTrackable.out << "\n"
104
+
105
+ data
106
+ end
107
+
108
+ def fetch_video_url(event_action)
109
+ index = nil
110
+ @config.video_url_base.each do |base|
111
+ index = event_action.index base
112
+ break if index.present?
113
+ end
114
+ if index.present?
115
+ trailing_index = event_action.index('/playlist.m3u8') || event_action.length
116
+ key = event_action.slice(index...trailing_index)
117
+ else
118
+ key = event_action
119
+ end
120
+ end
121
+
122
+ def get_entity(video_url)
123
+ @config.video_plays_entity_fetcher.call(video_url)
124
+ end
125
+
126
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+ require 'rails'
3
+ require 'google/api_client'
4
+
5
+ module GaTrackable
6
+ require 'ga_trackable/configuration'
7
+ require 'ga_trackable/version'
8
+ require 'ga_trackable/trackable'
9
+ require 'ga_trackable/base_fetcher'
10
+ require 'ga_trackable/page_views_fetcher'
11
+ require 'ga_trackable/video_plays_fetcher'
12
+ require 'ga_trackable/engine'
13
+
14
+ InvalidConfigurationError = Class.new(StandardError)
15
+
16
+ class << self
17
+
18
+ def setup(&blk)
19
+ @config ||= GaTrackable::Configuration.new(&blk)
20
+
21
+ if @config.invalid?
22
+ msg = "GaTrackable configuration ERROR:\n"
23
+ raise InvalidConfigurationError, msg + @config.errors.full_messages.join("\n")
24
+ end
25
+
26
+ @config
27
+ end
28
+
29
+ def reset
30
+ @config = nil
31
+ end
32
+
33
+ def config
34
+ @config || raise(InvalidConfigurationError, 'GaTrackable is not configured!')
35
+ end
36
+
37
+ def client
38
+ @client ||= begin
39
+ client = Google::APIClient.new(
40
+ application_name: config.app_name,
41
+ application_version: config.app_version
42
+ )
43
+ key = Google::APIClient::PKCS12.load_key(config.secret_path, config.secret_key)
44
+ service_account = Google::APIClient::JWTAsserter.new(config.issuer_email, config.scope, key)
45
+ client.authorization = service_account.authorize
46
+ client
47
+ end
48
+ end
49
+
50
+ def analytics
51
+ @analytics ||= client.discovered_api('analytics', 'v3')
52
+ end
53
+
54
+ delegate :out, to: :config
55
+
56
+ end
57
+ end
metadata ADDED
@@ -0,0 +1,114 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ga_trackable
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Yury
8
+ - Kotov
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2016-11-07 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rails
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ">="
19
+ - !ruby/object:Gem::Version
20
+ version: '0'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ version: '0'
28
+ - !ruby/object:Gem::Dependency
29
+ name: google-api-client
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - '='
33
+ - !ruby/object:Gem::Version
34
+ version: 0.8.6
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - '='
40
+ - !ruby/object:Gem::Version
41
+ version: 0.8.6
42
+ - !ruby/object:Gem::Dependency
43
+ name: activemodel
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ type: :runtime
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ - !ruby/object:Gem::Dependency
57
+ name: colorize
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ type: :runtime
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ description: A Ruby wrapper for tracking via Google Analytics API
71
+ email:
72
+ - non-gi-suong@ya.ru
73
+ executables: []
74
+ extensions: []
75
+ extra_rdoc_files: []
76
+ files:
77
+ - LICENSE
78
+ - README.md
79
+ - Rakefile
80
+ - lib/ga_trackable.rb
81
+ - lib/ga_trackable/base_fetcher.rb
82
+ - lib/ga_trackable/configuration.rb
83
+ - lib/ga_trackable/engine.rb
84
+ - lib/ga_trackable/page_views_fetcher.rb
85
+ - lib/ga_trackable/tasks/ga_trackable.rake
86
+ - lib/ga_trackable/trackable.rb
87
+ - lib/ga_trackable/version.rb
88
+ - lib/ga_trackable/video_plays_fetcher.rb
89
+ homepage: https://github.com/httplab/ga_trackable
90
+ licenses:
91
+ - MIT
92
+ metadata: {}
93
+ post_install_message:
94
+ rdoc_options: []
95
+ require_paths:
96
+ - lib
97
+ required_ruby_version: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ required_rubygems_version: !ruby/object:Gem::Requirement
103
+ requirements:
104
+ - - ">="
105
+ - !ruby/object:Gem::Version
106
+ version: '0'
107
+ requirements: []
108
+ rubyforge_project:
109
+ rubygems_version: 2.5.1
110
+ signing_key:
111
+ specification_version: 4
112
+ summary: A Ruby wrapper for page views and video plays tracking via Google Analytics
113
+ API
114
+ test_files: []