searchjoy 1.0.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/LICENSE.txt +1 -1
- data/README.md +12 -5
- data/app/controllers/searchjoy/searches_controller.rb +4 -4
- data/app/views/layouts/searchjoy/application.html.erb +5 -4
- data/app/views/searchjoy/searches/index.html.erb +2 -2
- data/app/views/searchjoy/searches/overview.html.erb +2 -2
- data/app/views/searchjoy/searches/stream.html.erb +2 -2
- data/lib/searchjoy/engine.rb +1 -1
- data/lib/searchjoy/version.rb +1 -1
- data/lib/searchjoy.rb +6 -12
- metadata +10 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c6e0ac0fd71243df3a3395c6ab793fe20d523ed435634b3adf73c44ac58aa167
|
4
|
+
data.tar.gz: 83708806572742373d3531750d867bdf9c4338df15546f4361e8d0b927330099
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 94f1c69497cb80375308e6694c7b43731f75baf93073c26baf16b446fb65fc6b335d252882f42e1391dd0f242b1a7b7e42587e3908cbf6db36a603fdf78a4477
|
7
|
+
data.tar.gz: b1eb7619d49602c90ca34dcae225c89d095c4357ee57970f61ac73d5b4ba336feccabb28eb4db2a9974215fe5c8d988441b2390e43bfac7936dd54ef91433869
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
## 1.2.0 (2024-06-24)
|
2
|
+
|
3
|
+
- Dropped support for Ruby < 3.1 and Rails < 6.1
|
4
|
+
|
5
|
+
## 1.1.0 (2023-02-07)
|
6
|
+
|
7
|
+
- Improved dashboard labels
|
8
|
+
- Improved CSP support
|
9
|
+
- Dropped support for Ruby < 2.7 and Rails < 6
|
10
|
+
|
1
11
|
## 1.0.0 (2022-05-10)
|
2
12
|
|
3
13
|
- Added support for multiple conversions per search
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -7,14 +7,14 @@ Search analytics made easy
|
|
7
7
|
[![Screenshot](https://searchjoy.dokkuapp.com/assets/searchjoy-7be12d922ca8b31b7d7440e618b0c666698a4b15752653a0c5c45e3dd2737142.png)](https://searchjoy.dokkuapp.com/)
|
8
8
|
|
9
9
|
- view searches in real-time
|
10
|
-
- track
|
10
|
+
- track conversion rate week over week
|
11
11
|
- monitor the performance of top searches
|
12
12
|
|
13
|
-
Works with any search platform, including Elasticsearch, Sphinx, and Solr
|
13
|
+
Works with any search platform, including Elasticsearch, OpenSearch, Sphinx, and Solr
|
14
14
|
|
15
15
|
:cupid: An amazing companion to [Searchkick](https://github.com/ankane/searchkick)
|
16
16
|
|
17
|
-
[![Build Status](https://github.com/ankane/searchjoy/workflows/build/badge.svg
|
17
|
+
[![Build Status](https://github.com/ankane/searchjoy/actions/workflows/build.yml/badge.svg)](https://github.com/ankane/searchjoy/actions)
|
18
18
|
|
19
19
|
## Installation
|
20
20
|
|
@@ -122,7 +122,11 @@ ENV["SEARCHJOY_PASSWORD"] = "secret"
|
|
122
122
|
Data should only be retained for as long as it’s needed. Delete older data with:
|
123
123
|
|
124
124
|
```ruby
|
125
|
-
Searchjoy::Search.where("created_at < ?", 1.year.ago).
|
125
|
+
Searchjoy::Search.where("created_at < ?", 1.year.ago).find_in_batches do |searches|
|
126
|
+
search_ids = searches.map(&:id)
|
127
|
+
Searchjoy::Conversion.where(search_id: search_ids).delete_all
|
128
|
+
Searchjoy::Search.where(id: search_ids).delete_all
|
129
|
+
end
|
126
130
|
```
|
127
131
|
|
128
132
|
You can use [Rollup](https://github.com/ankane/rollup) to aggregate important data before you do.
|
@@ -134,7 +138,10 @@ Searchjoy::Search.rollup("Searches")
|
|
134
138
|
Delete data for a specific user with:
|
135
139
|
|
136
140
|
```ruby
|
137
|
-
|
141
|
+
user_id = 123
|
142
|
+
search_ids = Searchjoy::Search.where(user_id: user_id).pluck(:id)
|
143
|
+
Searchjoy::Conversion.where(search_id: search_ids).delete_all
|
144
|
+
Searchjoy::Search.where(id: search_ids).delete_all
|
138
145
|
```
|
139
146
|
|
140
147
|
## Customize
|
@@ -34,12 +34,12 @@ module Searchjoy
|
|
34
34
|
|
35
35
|
relation = Searchjoy::Search.where(search_type: params[:search_type])
|
36
36
|
@searches_by_week = relation.group_by_period(period, :created_at, time_zone: @time_zone, range: @time_range).count
|
37
|
-
@
|
37
|
+
@converted_by_week = relation.where.not(converted_at: nil).group_by_period(period, :created_at, time_zone: @time_zone, range: @time_range).count
|
38
38
|
@top_searches = @searches.first(5)
|
39
39
|
@bad_conversion_rate = @searches.sort_by { |s| [s["conversion_rate"].to_f, s["query"]] }.first(5).select { |s| s["conversion_rate"] < 50 }
|
40
40
|
@conversion_rate_by_week = {}
|
41
41
|
@searches_by_week.each do |week, searches_count|
|
42
|
-
@conversion_rate_by_week[week] = searches_count > 0 ? (100.0 * @
|
42
|
+
@conversion_rate_by_week[week] = searches_count > 0 ? (100.0 * @converted_by_week[week] / searches_count).round : 0
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
@@ -87,7 +87,7 @@ module Searchjoy
|
|
87
87
|
def set_searches
|
88
88
|
@limit = params[:limit] || Searchjoy.top_searches
|
89
89
|
relation = Searchjoy::Search
|
90
|
-
.select("normalized_query, COUNT(*) as searches_count, COUNT(converted_at) as
|
90
|
+
.select("normalized_query, COUNT(*) as searches_count, COUNT(converted_at) as converted_count, AVG(results_count) as avg_results_count")
|
91
91
|
.where(created_at: @time_range, search_type: @search_type)
|
92
92
|
.group(:normalized_query)
|
93
93
|
.order(searches_count: :desc, normalized_query: :asc)
|
@@ -95,7 +95,7 @@ module Searchjoy
|
|
95
95
|
# get array of hashes for performance
|
96
96
|
@searches = Searchjoy::Search.connection.select_all(relation.to_sql).to_a
|
97
97
|
@searches.each do |search|
|
98
|
-
search["conversion_rate"] = 100 * search["
|
98
|
+
search["conversion_rate"] = 100 * search["converted_count"].to_i / search["searches_count"].to_f
|
99
99
|
end
|
100
100
|
end
|
101
101
|
end
|
@@ -4,6 +4,7 @@
|
|
4
4
|
<title>Searchjoy</title>
|
5
5
|
|
6
6
|
<meta charset="utf-8" />
|
7
|
+
<%= csp_meta_tag %>
|
7
8
|
|
8
9
|
<style>
|
9
10
|
body {
|
@@ -289,9 +290,9 @@
|
|
289
290
|
</style>
|
290
291
|
|
291
292
|
<% if defined?(Propshaft::Railtie) %>
|
292
|
-
<%= javascript_include_tag "chartkick", "Chart.bundle", "searchjoy/litepicker", "searchjoy/application" %>
|
293
|
+
<%= javascript_include_tag "chartkick", "Chart.bundle", "searchjoy/litepicker", "searchjoy/application", nonce: true %>
|
293
294
|
<% else %>
|
294
|
-
<%= javascript_include_tag "searchjoy/application" %>
|
295
|
+
<%= javascript_include_tag "searchjoy/application", nonce: true %>
|
295
296
|
<% end %>
|
296
297
|
</head>
|
297
298
|
<body>
|
@@ -314,7 +315,7 @@
|
|
314
315
|
<%= @time_range.first.strftime("%b %-e, %Y") %> to <%= @time_range.last.strftime("%b %-e, %Y") %>
|
315
316
|
</span>
|
316
317
|
<span class="text-muted"><%= @time_zone.name.sub(" (US & Canada)", "") %></span>
|
317
|
-
|
318
|
+
<%= javascript_tag nonce: true do %>
|
318
319
|
var startDate = <%= raw json_escape(@time_range.first.to_json) %>;
|
319
320
|
var endDate = <%= raw json_escape(@time_range.last.to_json) %>;
|
320
321
|
new Litepicker({
|
@@ -337,7 +338,7 @@
|
|
337
338
|
window.location.href = window.location.pathname + "?" + params.toString();
|
338
339
|
}
|
339
340
|
});
|
340
|
-
|
341
|
+
<% end %>
|
341
342
|
<% end %>
|
342
343
|
</div>
|
343
344
|
</div>
|
@@ -8,7 +8,7 @@
|
|
8
8
|
<tr>
|
9
9
|
<th>Query</th>
|
10
10
|
<th class="num" style="width: 20%;"><%= link_to "Searches", searches_path(search_type: params[:search_type], **@time_params), class: ("active" if params[:sort] != "conversion_rate") %></th>
|
11
|
-
<th class="num" style="width: 20%;">
|
11
|
+
<th class="num" style="width: 20%;">Converted</th>
|
12
12
|
<th class="num" style="width: 20%;"><%= link_to "%", searches_path(search_type: params[:search_type], sort: "conversion_rate", **@time_params), class: ("active" if params[:sort] == "conversion_rate") %></th>
|
13
13
|
<th class="num" style="width: 20%;">Avg Results</th>
|
14
14
|
</tr>
|
@@ -18,7 +18,7 @@
|
|
18
18
|
<tr>
|
19
19
|
<td><%= search["normalized_query"] %></td>
|
20
20
|
<td class="num"><%= search["searches_count"] %></td>
|
21
|
-
<td class="num"><%= search["
|
21
|
+
<td class="num"><%= search["converted_count"] %></td>
|
22
22
|
<td class="num"><%= number_to_percentage search["conversion_rate"].to_f, precision: 0 %></td>
|
23
23
|
<td class="num"><%= search["avg_results_count"].to_f.round %></td>
|
24
24
|
</tr>
|
@@ -23,7 +23,7 @@
|
|
23
23
|
<table>
|
24
24
|
<thead>
|
25
25
|
<tr>
|
26
|
-
<th>Low
|
26
|
+
<th>Low Conversion Rate</th>
|
27
27
|
<th class="num"><%= link_to "View all", searches_path(search_type: @search_type, sort: "conversion_rate", **@time_params) %></th>
|
28
28
|
</tr>
|
29
29
|
</thead>
|
@@ -45,4 +45,4 @@
|
|
45
45
|
|
46
46
|
<h2>Volume</h2>
|
47
47
|
|
48
|
-
<%= line_chart [{name: "Searches", data: @searches_by_week}, {name: "
|
48
|
+
<%= line_chart [{name: "Searches", data: @searches_by_week}, {name: "Converted", data: @converted_by_week}] %>
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
<table id="stream"></table>
|
4
4
|
|
5
|
-
|
5
|
+
<%= javascript_tag nonce: true do %>
|
6
6
|
function load(element, path) {
|
7
7
|
var request = new XMLHttpRequest();
|
8
8
|
request.open("GET", path, true);
|
@@ -20,4 +20,4 @@
|
|
20
20
|
setTimeout(fetchRecentSearches, 5 * 1000);
|
21
21
|
}
|
22
22
|
fetchRecentSearches();
|
23
|
-
|
23
|
+
<% end %>
|
data/lib/searchjoy/engine.rb
CHANGED
@@ -4,7 +4,7 @@ module Searchjoy
|
|
4
4
|
|
5
5
|
initializer "searchjoy" do |app|
|
6
6
|
if app.config.respond_to?(:assets)
|
7
|
-
if defined?(Sprockets) && Sprockets::VERSION >=
|
7
|
+
if defined?(Sprockets) && Sprockets::VERSION.to_i >= 4
|
8
8
|
app.config.assets.precompile << "searchjoy/application.js"
|
9
9
|
else
|
10
10
|
# use a proc instead of a string
|
data/lib/searchjoy/version.rb
CHANGED
data/lib/searchjoy.rb
CHANGED
@@ -4,8 +4,8 @@ require "chartkick"
|
|
4
4
|
require "groupdate"
|
5
5
|
|
6
6
|
# modules
|
7
|
-
|
8
|
-
|
7
|
+
require_relative "searchjoy/track"
|
8
|
+
require_relative "searchjoy/version"
|
9
9
|
|
10
10
|
module Searchjoy
|
11
11
|
# time zone
|
@@ -44,19 +44,13 @@ module Searchjoy
|
|
44
44
|
created_at: search.converted_at
|
45
45
|
}
|
46
46
|
end
|
47
|
-
|
48
|
-
Searchjoy::Conversion.insert_all(conversions)
|
49
|
-
else
|
50
|
-
Searchjoy::Conversion.transaction do
|
51
|
-
Searchjoy::Conversion.create!(conversions)
|
52
|
-
end
|
53
|
-
end
|
47
|
+
Searchjoy::Conversion.insert_all(conversions)
|
54
48
|
end
|
55
49
|
end
|
56
50
|
end
|
57
51
|
|
58
52
|
if defined?(Rails)
|
59
|
-
|
60
|
-
|
61
|
-
Searchjoy.attach_to_searchkick!
|
53
|
+
require_relative "searchjoy/engine"
|
54
|
+
elsif defined?(Searchkick)
|
55
|
+
Searchjoy.attach_to_searchkick!
|
62
56
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: searchjoy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Kane
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-06-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: chartkick
|
@@ -16,42 +16,42 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '5'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '5'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: groupdate
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '6'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '6'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: activerecord
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
47
|
+
version: '6.1'
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
54
|
+
version: '6.1'
|
55
55
|
description:
|
56
56
|
email: andrew@ankane.org
|
57
57
|
executables: []
|
@@ -91,14 +91,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
91
91
|
requirements:
|
92
92
|
- - ">="
|
93
93
|
- !ruby/object:Gem::Version
|
94
|
-
version: '
|
94
|
+
version: '3.1'
|
95
95
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
96
96
|
requirements:
|
97
97
|
- - ">="
|
98
98
|
- !ruby/object:Gem::Version
|
99
99
|
version: '0'
|
100
100
|
requirements: []
|
101
|
-
rubygems_version: 3.
|
101
|
+
rubygems_version: 3.5.11
|
102
102
|
signing_key:
|
103
103
|
specification_version: 4
|
104
104
|
summary: Search analytics made easy
|