ga_trackable 0.0.1

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.
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: []