trueandco_analytics 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|