trueandco_analytics 0.3.0
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 +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +152 -0
- data/Rakefile +36 -0
- data/app/assets/javascripts/trueandco_analytics.js +170 -0
- data/app/commands/trueandco_analytics/arr_jsons_to_arr_hash.rb +20 -0
- data/app/commands/trueandco_analytics/metric_c/add_list.rb +65 -0
- data/app/commands/trueandco_analytics/report_c/generate.rb +31 -0
- data/app/commands/trueandco_analytics/session_c/create.rb +65 -0
- data/app/commands/trueandco_analytics/session_c/put_data.rb +46 -0
- data/app/commands/trueandco_analytics/user_c/create_or_update_user_if_exist.rb +41 -0
- data/app/controllers/trueandco_analytics/application_controller.rb +5 -0
- data/app/controllers/trueandco_analytics/reciver_controller.rb +19 -0
- data/app/models/trueandco_analytics/application_record.rb +5 -0
- data/app/models/trueandco_analytics/metric_user.rb +8 -0
- data/app/models/trueandco_analytics/metric_user_session.rb +8 -0
- data/app/models/trueandco_analytics/metric_user_visit.rb +8 -0
- data/app/views/trueandco_analytics/receiver/pull_user_statistic.erb +0 -0
- data/app/workers/trueandco_analytics/user_session_metric_worker.rb +21 -0
- data/config/routes.rb +3 -0
- data/config/secrets.yml +2 -0
- data/db/migrate/20170802133950_create_metric_users.rb +19 -0
- data/db/migrate/20170802134044_create_metric_user_visits.rb +20 -0
- data/db/migrate/20170802134059_create_metric_user_sessions.rb +27 -0
- data/exe/trueandco_analytics +28 -0
- data/lib/extension_string.rb +20 -0
- data/lib/generators/trueandco_analytics/install_generator.rb +14 -0
- data/lib/generators/trueandco_analytics/templates/trueandco_analytics.rb +37 -0
- data/lib/trueandco_analytics/cli/common.rb +49 -0
- data/lib/trueandco_analytics/cli/report.rb +51 -0
- data/lib/trueandco_analytics/config/params.rb +81 -0
- data/lib/trueandco_analytics/engine.rb +31 -0
- data/lib/trueandco_analytics/helpers/trueandco_analytics_helper.rb +35 -0
- data/lib/trueandco_analytics/locales/en.yml +16 -0
- data/lib/trueandco_analytics/modules/info.rb +21 -0
- data/lib/trueandco_analytics/reports/application_report.rb +61 -0
- data/lib/trueandco_analytics/reports/details_report.rb +24 -0
- data/lib/trueandco_analytics/reports/page_buy_in_date_range_report.rb +29 -0
- data/lib/trueandco_analytics/services/logger.rb +24 -0
- data/lib/trueandco_analytics/services/redis_connect.rb +12 -0
- data/lib/trueandco_analytics/services/reports.rb +30 -0
- data/lib/trueandco_analytics/services/workers.rb +14 -0
- data/lib/trueandco_analytics/version.rb +3 -0
- data/lib/trueandco_analytics.rb +37 -0
- metadata +242 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 2eddcffa3c6a13247a6f2ea46e5cde544fd73fbc
|
4
|
+
data.tar.gz: ef377598828ff1be656935568fab8d2c1d2a0311
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1654ffbb2a22a87e2e5930cd0978284971e9ebbaf8b6bf69f45c151fdf0a12bd2a8d94f46fa87adefad7c4587deefabb249482d2b920559d0ae99bfd94888c97
|
7
|
+
data.tar.gz: 3e0a6bb73989e4f76d6e9bf02ebbda08e1372b537d71a72df9ac6bced523e8d81ba3313fb54c1b7a38003dc5ca7c3784b8881beaf142c02ebfbd82503bfabb5c
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2017
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,152 @@
|
|
1
|
+
# Trueandco_analytics
|
2
|
+
**Trueandco_analytics** Gems for authentication and authorization
|
3
|
+
|
4
|
+
## About
|
5
|
+
Many systems analysts do not provide data about the specific user. This gem allows administrators to obtain reports on a particular user and common page statistics
|
6
|
+
|
7
|
+
|
8
|
+
## Installation
|
9
|
+
|
10
|
+
1. You shall have (redis, sidekiq, mysql) on your server.
|
11
|
+
2. You have to include gems in your Gemfile:
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
gem 'trueandco_analytics'
|
15
|
+
```
|
16
|
+
|
17
|
+
3. And then to start
|
18
|
+
|
19
|
+
```ruby
|
20
|
+
bundle
|
21
|
+
```
|
22
|
+
|
23
|
+
4. To start the initialiser, for detailed configured gem
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
rails g trueandco_analytics:install
|
27
|
+
```
|
28
|
+
|
29
|
+
After
|
30
|
+
|
31
|
+
```ruby
|
32
|
+
rake db:migrate
|
33
|
+
```
|
34
|
+
or
|
35
|
+
```ruby
|
36
|
+
rails db:migrate
|
37
|
+
```
|
38
|
+
That create 3 tables:
|
39
|
+
|
40
|
+
`metric_users`, `metric_user_sessions`, `metric_user_visits`
|
41
|
+
|
42
|
+
`metric_users` Info about users
|
43
|
+
`metric_user_sessions` Info about user sesssions
|
44
|
+
`metric_user_visits` Pages which were visited by the user within the session
|
45
|
+
|
46
|
+
Add assetcs
|
47
|
+
```js
|
48
|
+
//= require trueandco_analytics
|
49
|
+
```
|
50
|
+
Add helper ` track_user_behavior` to head for tracking
|
51
|
+
```html
|
52
|
+
<!DOCTYPE html>
|
53
|
+
<html>
|
54
|
+
<head>
|
55
|
+
<title>Example</title>
|
56
|
+
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %>
|
57
|
+
<%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
|
58
|
+
<%= csrf_meta_tags %>
|
59
|
+
<%= track_user_behavior %>
|
60
|
+
</head>
|
61
|
+
```
|
62
|
+
|
63
|
+
Add the mointing address
|
64
|
+
```ruby
|
65
|
+
mount TrueandcoAnalytics::Engine, at: "/metric"
|
66
|
+
```
|
67
|
+
And you need to listen queue `user_metric`
|
68
|
+
```ruby
|
69
|
+
bundle exec sidekiq --queue=user_metric
|
70
|
+
```
|
71
|
+
Need set in app
|
72
|
+
```ruby
|
73
|
+
config.eager_load = true
|
74
|
+
```
|
75
|
+
The application must have a route `root`
|
76
|
+
|
77
|
+
For use of the console mode. it is necessary to specify the current database.
|
78
|
+
```ruby
|
79
|
+
config.db_connect = {
|
80
|
+
database: 'development_db_name',
|
81
|
+
username: 'ivan',
|
82
|
+
password: '3443555',
|
83
|
+
host: '127.0.0.1',
|
84
|
+
port: 3306
|
85
|
+
}
|
86
|
+
```
|
87
|
+
It is possible to include the logging mode, having specified the name
|
88
|
+
```ruby
|
89
|
+
config.log = 'name of log'
|
90
|
+
```
|
91
|
+
|
92
|
+
|
93
|
+
## Usage
|
94
|
+
|
95
|
+
Now we can take data in a convenient format.
|
96
|
+
It is necessary to specify the report and a format of data
|
97
|
+
So far only arr, csv is available
|
98
|
+
|
99
|
+
For this we use the service object `::TrueandcoAnalytics::Reports`
|
100
|
+
|
101
|
+
Available formats
|
102
|
+
```ruby
|
103
|
+
::TrueandcoAnalytics::Reports.available_formats
|
104
|
+
```
|
105
|
+
List of reports
|
106
|
+
```ruby
|
107
|
+
::TrueandcoAnalytics::Reports.available_reports
|
108
|
+
```
|
109
|
+
Get report obj with method report_name and data
|
110
|
+
```ruby
|
111
|
+
::TrueandcoAnalytics::Reports.get_report_obj('page_buy_in_date_range_report', 'csv')
|
112
|
+
::TrueandcoAnalytics::Reports.get_report_obj('page_buy_in_date_range_report', 'csv', datetme_start, datetime_end)
|
113
|
+
```
|
114
|
+
|
115
|
+
### Usage console mod
|
116
|
+
|
117
|
+
bundle exec trueandco_analytics -h
|
118
|
+
|
119
|
+
## Settings
|
120
|
+
|
121
|
+
* Time survey Analytics seconds
|
122
|
+
`config.time_survey = 15`
|
123
|
+
|
124
|
+
* Specify the method available in the ApplicationController to the receiving user object. Containing id, email.
|
125
|
+
`config.user_method = 'current_user'`
|
126
|
+
|
127
|
+
* Specify css the selector class for the button purchase
|
128
|
+
`config.buy_selector_class = 'buy'`
|
129
|
+
|
130
|
+
* Specify the database where redis will store the statistics for the session user
|
131
|
+
```ruby
|
132
|
+
config.connect_redis = {
|
133
|
+
#url: "redis://your_host:6379",
|
134
|
+
#redis_password: '',
|
135
|
+
redis_db: 1
|
136
|
+
}
|
137
|
+
```
|
138
|
+
|
139
|
+
* Specify Sidekiq config
|
140
|
+
`config.sidekiq_configure_client_url = 'redis://localhost:6379/1'`
|
141
|
+
`config.sidekiq_configure_server_url = 'redis://localhost:6379/1'`
|
142
|
+
`config.sidekiq_configure_namespace = 'metric'`
|
143
|
+
|
144
|
+
|
145
|
+
## Ruby version tested
|
146
|
+
|
147
|
+
**2.2.4**
|
148
|
+
|
149
|
+
## Contributing
|
150
|
+
|
151
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/Rattt/trueandco_analytics. This project is intended to be a safe,
|
152
|
+
welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
data/Rakefile
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
begin
|
2
|
+
require 'bundler/setup'
|
3
|
+
rescue LoadError
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'rdoc/task'
|
8
|
+
|
9
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
10
|
+
rdoc.rdoc_dir = 'rdoc'
|
11
|
+
rdoc.title = 'TrueandcoAnalytics'
|
12
|
+
rdoc.options << '--line-numbers'
|
13
|
+
rdoc.rdoc_files.include('README.md')
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
|
+
end
|
16
|
+
|
17
|
+
APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
|
18
|
+
load 'rails/tasks/engine.rake'
|
19
|
+
|
20
|
+
|
21
|
+
load 'rails/tasks/statistics.rake'
|
22
|
+
|
23
|
+
|
24
|
+
|
25
|
+
require 'bundler/gem_tasks'
|
26
|
+
|
27
|
+
require 'rake/testtask'
|
28
|
+
|
29
|
+
Rake::TestTask.new(:test) do |t|
|
30
|
+
t.libs << 'test'
|
31
|
+
t.pattern = 'test/**/*_test.rb'
|
32
|
+
t.verbose = false
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
task default: :test
|
@@ -0,0 +1,170 @@
|
|
1
|
+
var userLog = (function(){
|
2
|
+
//
|
3
|
+
// Private variables
|
4
|
+
//
|
5
|
+
var defaults = {
|
6
|
+
|
7
|
+
// Available functionality
|
8
|
+
clickCount: true,
|
9
|
+
clickDetails: true,
|
10
|
+
|
11
|
+
// Action Item
|
12
|
+
actionItem: {
|
13
|
+
processOnAction: false,
|
14
|
+
selector: '',
|
15
|
+
event: ''
|
16
|
+
},
|
17
|
+
processTime: 15,
|
18
|
+
processData: function(results, statistics_url){
|
19
|
+
console.log(results);
|
20
|
+
},
|
21
|
+
},
|
22
|
+
// End results, what is shown to the user
|
23
|
+
results = {
|
24
|
+
userReferrer: '',
|
25
|
+
time: {
|
26
|
+
totalTime: 0,
|
27
|
+
timeOnPage: 0,
|
28
|
+
timestamp: 0
|
29
|
+
},
|
30
|
+
clicks: {
|
31
|
+
clickCount:0,
|
32
|
+
clickDetails: []
|
33
|
+
},
|
34
|
+
|
35
|
+
},
|
36
|
+
support = !!document.querySelector && !!document.addEventListener,
|
37
|
+
data_receiver = '',
|
38
|
+
app_token = '',
|
39
|
+
settings;
|
40
|
+
|
41
|
+
// Helper Functions
|
42
|
+
var helperActions = {
|
43
|
+
|
44
|
+
userReferrer: function (){
|
45
|
+
result = document.referrer;
|
46
|
+
results.userReferrer = 10;
|
47
|
+
},
|
48
|
+
|
49
|
+
/**
|
50
|
+
* Detect the X,Y coordinates of the mouse movement
|
51
|
+
* @private
|
52
|
+
*/
|
53
|
+
mouseMovement: function(){
|
54
|
+
document.addEventListener('mousemove', function(){
|
55
|
+
results.mouseMovements.push({
|
56
|
+
timestamp: Date.now(),
|
57
|
+
x: event.pageX,
|
58
|
+
y: event.pageY
|
59
|
+
});
|
60
|
+
});
|
61
|
+
},
|
62
|
+
}
|
63
|
+
|
64
|
+
/**
|
65
|
+
* Merge defaults with options
|
66
|
+
* @private
|
67
|
+
* @param {Object} default settings
|
68
|
+
* @param {Object} user options
|
69
|
+
* @returns {Object} merged object
|
70
|
+
*/
|
71
|
+
function getSettings(defaults, options){
|
72
|
+
var option;
|
73
|
+
for(option in options){
|
74
|
+
if(options.hasOwnProperty(option)){
|
75
|
+
defaults[option] = options[option];
|
76
|
+
}
|
77
|
+
}
|
78
|
+
return defaults;
|
79
|
+
}
|
80
|
+
|
81
|
+
/**
|
82
|
+
* Initialize the event listeners
|
83
|
+
* @public
|
84
|
+
* @param {Object} user options
|
85
|
+
*/
|
86
|
+
function init(statistics_url, token, options){
|
87
|
+
if(!support) return;
|
88
|
+
data_receiver = statistics_url;
|
89
|
+
app_token = token;
|
90
|
+
|
91
|
+
// Extend default options
|
92
|
+
if (options && typeof options === "object") {
|
93
|
+
settings = getSettings(defaults, options);
|
94
|
+
}
|
95
|
+
|
96
|
+
document.addEventListener('DOMContentLoaded', function() {
|
97
|
+
|
98
|
+
// Countdown Timer
|
99
|
+
window.setInterval(function(){
|
100
|
+
if(document['visibilityState'] === 'visible'){
|
101
|
+
results.time.timeOnPage++;
|
102
|
+
}
|
103
|
+
results.time.totalTime++;
|
104
|
+
// Check if we need to process results
|
105
|
+
if(settings.processTime > 0 && results.time.totalTime % settings.processTime === 0){
|
106
|
+
processResults();
|
107
|
+
}
|
108
|
+
},1000);
|
109
|
+
results.time.timestamp = (function() {
|
110
|
+
return Math.round((+new Date())/1000);
|
111
|
+
})();
|
112
|
+
|
113
|
+
// Click registration, increment click counter and save click time+position
|
114
|
+
if(settings.clickCount || settings.clickDetails){
|
115
|
+
document.addEventListener('mouseup', function(){
|
116
|
+
if(settings.clickCount){
|
117
|
+
results.clicks.clickCount++;
|
118
|
+
}
|
119
|
+
if(settings.clickDetails){
|
120
|
+
results.clicks.clickDetails.push({
|
121
|
+
timestamp: Date.now(),
|
122
|
+
node: event.target.outerHTML,
|
123
|
+
x: event.pageX,
|
124
|
+
y: event.pageY
|
125
|
+
});
|
126
|
+
}
|
127
|
+
});
|
128
|
+
}
|
129
|
+
|
130
|
+
// Mouse movements
|
131
|
+
if(settings.mouseMovement){
|
132
|
+
helperActions.mouseMovement();
|
133
|
+
}
|
134
|
+
|
135
|
+
// referral
|
136
|
+
if(settings.userReferrer){
|
137
|
+
helperActions.userReferrer();
|
138
|
+
}
|
139
|
+
|
140
|
+
// Event Listener to porcess
|
141
|
+
if(settings.actionItem.processOnAction){
|
142
|
+
var node = document.querySelector(settings.actionItem.selector);
|
143
|
+
if(!!!node) throw new Error('Selector was not found.');
|
144
|
+
node.addEventListener(settings.actionItem.event, function(){
|
145
|
+
return processResults();
|
146
|
+
})
|
147
|
+
}
|
148
|
+
});
|
149
|
+
}
|
150
|
+
|
151
|
+
/**
|
152
|
+
* Calls provided function with results as parameter
|
153
|
+
* @public
|
154
|
+
*/
|
155
|
+
function processResults(){
|
156
|
+
if(settings.hasOwnProperty('processData')){
|
157
|
+
var result = settings.processData.call(undefined, results, data_receiver, app_token);
|
158
|
+
results.clicks.clickDetails = []
|
159
|
+
return result;
|
160
|
+
}
|
161
|
+
return false;
|
162
|
+
}
|
163
|
+
|
164
|
+
|
165
|
+
// Module pattern, only expose necessary methods
|
166
|
+
return {
|
167
|
+
init: init,
|
168
|
+
processResults: processResults,
|
169
|
+
};
|
170
|
+
})();
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module TrueandcoAnalytics
|
2
|
+
class ArrJsonsToArrHash
|
3
|
+
|
4
|
+
def initialize(arr_json)
|
5
|
+
@arr_json = arr_json
|
6
|
+
end
|
7
|
+
|
8
|
+
def execute
|
9
|
+
result = []
|
10
|
+
@arr_json.each do |json|
|
11
|
+
result << JSON.parse(json)
|
12
|
+
end
|
13
|
+
result
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
attr_reader :arr_json
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module TrueandcoAnalytics
|
2
|
+
module MetricC
|
3
|
+
class AddList
|
4
|
+
|
5
|
+
def initialize(metric_user, session, user_session_data)
|
6
|
+
if metric_user.nil? || session.nil? || user_session_data.nil?
|
7
|
+
raise ArgumentError.new("#{self.to_s} metric_user=#{metric_user}
|
8
|
+
session=#{session} user_session_data=#{user_session_data}")
|
9
|
+
end
|
10
|
+
@metric_user = metric_user
|
11
|
+
@session = session
|
12
|
+
@user_session_data = user_session_data
|
13
|
+
end
|
14
|
+
|
15
|
+
def execute
|
16
|
+
uniq_pages = info_uniq_page
|
17
|
+
return if uniq_pages.nil?
|
18
|
+
uniq_pages.each do |page|
|
19
|
+
data = {
|
20
|
+
metric_user: metric_user,
|
21
|
+
metric_user_session: session,
|
22
|
+
page_path: page['page_path'],
|
23
|
+
user_action: page['clicks']['clickDetails'].to_json,
|
24
|
+
time_s: page['time']['timeOnPage'],
|
25
|
+
is_buy: page['clicks']['clickDetails'].length > 0
|
26
|
+
}
|
27
|
+
MetricUserVisit.create(data)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
attr_reader :metric_user, :session, :user_session_data
|
34
|
+
|
35
|
+
def info_uniq_page
|
36
|
+
length = user_session_data.length
|
37
|
+
return user_session_data if length < 2
|
38
|
+
results = []
|
39
|
+
page = user_session_data[0]['page_path']
|
40
|
+
clickDetails = []
|
41
|
+
index = 0
|
42
|
+
while index < length - 1
|
43
|
+
unless user_session_data[index]['clicks']['clickDetails'].empty?
|
44
|
+
clickDetails = user_session_data[index]['clicks']['clickDetails']
|
45
|
+
end
|
46
|
+
index += 1
|
47
|
+
unless page == user_session_data[index]['page_path']
|
48
|
+
data = user_session_data[index - 1]
|
49
|
+
data['clicks']['clickDetails'] = clickDetails
|
50
|
+
results << data
|
51
|
+
page = user_session_data[index]['page_path']
|
52
|
+
clickDetails = []
|
53
|
+
end
|
54
|
+
end
|
55
|
+
data = user_session_data[index]
|
56
|
+
unless data['clicks']['clickDetails'].empty?
|
57
|
+
clickDetails = data['clicks']['clickDetails']
|
58
|
+
end
|
59
|
+
data['clicks']['clickDetails'] = clickDetails
|
60
|
+
results << data
|
61
|
+
results
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|