searchjoy 0.5.1 → 1.1.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 +4 -4
- data/CHANGELOG.md +53 -0
- data/LICENSE.txt +1 -1
- data/README.md +60 -9
- data/app/controllers/searchjoy/searches_controller.rb +21 -9
- data/app/models/searchjoy/conversion.rb +8 -0
- data/app/models/searchjoy/search.rb +24 -4
- data/app/views/layouts/searchjoy/application.html.erb +8 -3
- 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/recent.html.erb +2 -1
- data/app/views/searchjoy/searches/stream.html.erb +3 -3
- data/lib/generators/searchjoy/templates/install.rb.tt +6 -1
- data/lib/searchjoy/engine.rb +1 -1
- data/lib/searchjoy/version.rb +1 -1
- data/lib/searchjoy.rb +24 -5
- metadata +12 -81
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d828271eb123a378fe3491da733c10c097f083dcdc9b6586fd3947c032f064b7
|
|
4
|
+
data.tar.gz: e907e0cd11b7c68e9431184add27fe79d3f35f573d221318e25e34a33a99847e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: fdfc1fd30d7e31156d6891eee806933cead952c6bb0cca8eb1c9579b279b8629809ca08eaa7e01b8035b728ffc3f7c32a769822106c01422577a1c4830d1ab73
|
|
7
|
+
data.tar.gz: c04d0eb16545d44431e962d7bb1e2fb177bd717a53049f0924c565eccc7fe53966c58e8a1eb10cf7656813c6ca9d265825d010a1a1cad15365acdcd8d1c9f69a
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
## 1.1.0 (2023-02-07)
|
|
2
|
+
|
|
3
|
+
- Improved dashboard labels
|
|
4
|
+
- Improved CSP support
|
|
5
|
+
- Dropped support for Ruby < 2.7 and Rails < 6
|
|
6
|
+
|
|
7
|
+
## 1.0.0 (2022-05-10)
|
|
8
|
+
|
|
9
|
+
- Added support for multiple conversions per search
|
|
10
|
+
- Added experimental support for Propshaft
|
|
11
|
+
- Dropped support for Ruby < 2.6 and Rails < 5.2
|
|
12
|
+
|
|
1
13
|
## 0.5.1 (2020-09-07)
|
|
2
14
|
|
|
3
15
|
- Use `datetime` type in migration
|
|
@@ -57,3 +69,44 @@ Breaking
|
|
|
57
69
|
## 0.1.0 (2016-08-23)
|
|
58
70
|
|
|
59
71
|
- Fixed Searchkick integration for `execute: false`
|
|
72
|
+
|
|
73
|
+
## 0.0.10 (2016-04-20)
|
|
74
|
+
|
|
75
|
+
- Fixed error when block passed to `search`
|
|
76
|
+
|
|
77
|
+
## 0.0.9 (2016-03-12)
|
|
78
|
+
|
|
79
|
+
- Fixed error with routes
|
|
80
|
+
|
|
81
|
+
## 0.0.8 (2015-12-12)
|
|
82
|
+
|
|
83
|
+
- Added `user_id` to searches
|
|
84
|
+
|
|
85
|
+
## 0.0.7 (2014-08-18)
|
|
86
|
+
|
|
87
|
+
- Fixed error with Searchkick 0.8
|
|
88
|
+
|
|
89
|
+
## 0.0.6 (2013-12-19)
|
|
90
|
+
|
|
91
|
+
- Fixed error with Rails 3
|
|
92
|
+
|
|
93
|
+
## 0.0.5 (2013-11-01)
|
|
94
|
+
|
|
95
|
+
- Renamed to Searchjoy
|
|
96
|
+
|
|
97
|
+
## 0.0.4 (2013-10-31)
|
|
98
|
+
|
|
99
|
+
- Renamed `converted` to `convert`
|
|
100
|
+
|
|
101
|
+
## 0.0.3 (2013-10-31)
|
|
102
|
+
|
|
103
|
+
- Added `conversion_name` option
|
|
104
|
+
- Added `converted` method
|
|
105
|
+
|
|
106
|
+
## 0.0.2 (2013-10-31)
|
|
107
|
+
|
|
108
|
+
- Added dashboard
|
|
109
|
+
|
|
110
|
+
## 0.0.1 (2013-10-24)
|
|
111
|
+
|
|
112
|
+
- First release
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
|
@@ -4,17 +4,17 @@ Search analytics made easy
|
|
|
4
4
|
|
|
5
5
|
[See it in action](https://searchjoy.dokkuapp.com/)
|
|
6
6
|
|
|
7
|
-
[](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
|
-
[](https://github.com/ankane/searchjoy/actions)
|
|
18
18
|
|
|
19
19
|
## Installation
|
|
20
20
|
|
|
@@ -70,8 +70,6 @@ Then, pass the values to the `track` option.
|
|
|
70
70
|
Item.search("apple", track: {user_id: 1, source: "web"})
|
|
71
71
|
```
|
|
72
72
|
|
|
73
|
-
It’s that easy.
|
|
74
|
-
|
|
75
73
|
## Track Conversions
|
|
76
74
|
|
|
77
75
|
First, choose a conversion metric. At Instacart, an item added to the cart from the search results page counts as a conversion.
|
|
@@ -121,16 +119,29 @@ ENV["SEARCHJOY_PASSWORD"] = "secret"
|
|
|
121
119
|
|
|
122
120
|
## Data Retention
|
|
123
121
|
|
|
124
|
-
Delete older data with:
|
|
122
|
+
Data should only be retained for as long as it’s needed. Delete older data with:
|
|
123
|
+
|
|
124
|
+
```ruby
|
|
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
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
You can use [Rollup](https://github.com/ankane/rollup) to aggregate important data before you do.
|
|
125
133
|
|
|
126
134
|
```ruby
|
|
127
|
-
Searchjoy::Search.
|
|
135
|
+
Searchjoy::Search.rollup("Searches")
|
|
128
136
|
```
|
|
129
137
|
|
|
130
138
|
Delete data for a specific user with:
|
|
131
139
|
|
|
132
140
|
```ruby
|
|
133
|
-
|
|
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
|
|
134
145
|
```
|
|
135
146
|
|
|
136
147
|
## Customize
|
|
@@ -167,6 +178,46 @@ Show the conversion name in the live stream
|
|
|
167
178
|
Searchjoy.conversion_name = ->(model) { model.name }
|
|
168
179
|
```
|
|
169
180
|
|
|
181
|
+
## Upgrading
|
|
182
|
+
|
|
183
|
+
### 1.0
|
|
184
|
+
|
|
185
|
+
Searchjoy now supports multiple conversions per search :tada:
|
|
186
|
+
|
|
187
|
+
Before updating the gem, create a migration with:
|
|
188
|
+
|
|
189
|
+
```ruby
|
|
190
|
+
create_table :searchjoy_conversions do |t|
|
|
191
|
+
t.references :search
|
|
192
|
+
t.references :convertable, polymorphic: true, index: {name: "index_searchjoy_conversions_on_convertable"}
|
|
193
|
+
t.datetime :created_at
|
|
194
|
+
end
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Deploy and run the migration, then update the gem.
|
|
198
|
+
|
|
199
|
+
You can optionally backfill the conversions table
|
|
200
|
+
|
|
201
|
+
```ruby
|
|
202
|
+
Searchjoy.backfill_conversions
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
And optionally remove `convertable` from searches
|
|
206
|
+
|
|
207
|
+
```ruby
|
|
208
|
+
remove_reference :searchjoy_searches, :convertable, polymorphic: true
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
You can stay with single conversions (and skip all the previous steps) by creating an initializer with:
|
|
212
|
+
|
|
213
|
+
```ruby
|
|
214
|
+
Searchjoy.multiple_conversions = false
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
## History
|
|
218
|
+
|
|
219
|
+
View the [changelog](https://github.com/ankane/searchjoy/blob/master/CHANGELOG.md)
|
|
220
|
+
|
|
170
221
|
## Contributing
|
|
171
222
|
|
|
172
223
|
Everyone is encouraged to help improve this project. Here are a few ways you can help:
|
|
@@ -23,23 +23,23 @@ module Searchjoy
|
|
|
23
23
|
duration = @time_range.last - @time_range.first
|
|
24
24
|
period =
|
|
25
25
|
if duration < 3.days # shows 48-72 data points (ends at current time)
|
|
26
|
-
|
|
26
|
+
:hour
|
|
27
27
|
elsif duration < 60.days
|
|
28
|
-
|
|
28
|
+
:day
|
|
29
29
|
elsif duration < 60.weeks # to make it easy to compare to same time last year
|
|
30
|
-
|
|
30
|
+
:week
|
|
31
31
|
else
|
|
32
|
-
|
|
32
|
+
:month
|
|
33
33
|
end
|
|
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
|
|
|
@@ -47,7 +47,12 @@ module Searchjoy
|
|
|
47
47
|
end
|
|
48
48
|
|
|
49
49
|
def recent
|
|
50
|
-
@searches = Searchjoy::Search.
|
|
50
|
+
@searches = Searchjoy::Search.order(created_at: :desc).limit(50)
|
|
51
|
+
if Searchjoy.multiple_conversions
|
|
52
|
+
@searches.includes!(conversions: :convertable)
|
|
53
|
+
else
|
|
54
|
+
@searches.includes!(:convertable)
|
|
55
|
+
end
|
|
51
56
|
render layout: false
|
|
52
57
|
end
|
|
53
58
|
|
|
@@ -81,9 +86,16 @@ module Searchjoy
|
|
|
81
86
|
|
|
82
87
|
def set_searches
|
|
83
88
|
@limit = params[:limit] || Searchjoy.top_searches
|
|
84
|
-
|
|
89
|
+
relation = Searchjoy::Search
|
|
90
|
+
.select("normalized_query, COUNT(*) as searches_count, COUNT(converted_at) as converted_count, AVG(results_count) as avg_results_count")
|
|
91
|
+
.where(created_at: @time_range, search_type: @search_type)
|
|
92
|
+
.group(:normalized_query)
|
|
93
|
+
.order(searches_count: :desc, normalized_query: :asc)
|
|
94
|
+
.limit(@limit)
|
|
95
|
+
# get array of hashes for performance
|
|
96
|
+
@searches = Searchjoy::Search.connection.select_all(relation.to_sql).to_a
|
|
85
97
|
@searches.each do |search|
|
|
86
|
-
search["conversion_rate"] = 100 * search["
|
|
98
|
+
search["conversion_rate"] = 100 * search["converted_count"].to_i / search["searches_count"].to_f
|
|
87
99
|
end
|
|
88
100
|
end
|
|
89
101
|
end
|
|
@@ -4,14 +4,34 @@ module Searchjoy
|
|
|
4
4
|
|
|
5
5
|
belongs_to :convertable, polymorphic: true, optional: true
|
|
6
6
|
belongs_to :user, optional: true
|
|
7
|
+
has_many :conversions
|
|
7
8
|
|
|
8
9
|
before_save :set_normalized_query
|
|
9
10
|
|
|
10
11
|
def convert(convertable = nil)
|
|
11
|
-
unless converted?
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
return unless Searchjoy.multiple_conversions || !converted?
|
|
13
|
+
|
|
14
|
+
# use transaction to keep consistent
|
|
15
|
+
self.class.transaction do
|
|
16
|
+
# make time consistent
|
|
17
|
+
now = Time.now
|
|
18
|
+
|
|
19
|
+
if Searchjoy.multiple_conversions
|
|
20
|
+
conversion =
|
|
21
|
+
conversions.create!(
|
|
22
|
+
convertable: convertable,
|
|
23
|
+
created_at: now
|
|
24
|
+
)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
unless converted?
|
|
28
|
+
self.converted_at = now
|
|
29
|
+
# check id instead of association
|
|
30
|
+
self.convertable = convertable if respond_to?(:convertable_id=)
|
|
31
|
+
save(validate: false)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
conversion
|
|
15
35
|
end
|
|
16
36
|
end
|
|
17
37
|
|
|
@@ -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 {
|
|
@@ -288,7 +289,11 @@
|
|
|
288
289
|
}
|
|
289
290
|
</style>
|
|
290
291
|
|
|
291
|
-
|
|
292
|
+
<% if defined?(Propshaft::Railtie) %>
|
|
293
|
+
<%= javascript_include_tag "chartkick", "Chart.bundle", "searchjoy/litepicker", "searchjoy/application", nonce: true %>
|
|
294
|
+
<% else %>
|
|
295
|
+
<%= javascript_include_tag "searchjoy/application", nonce: true %>
|
|
296
|
+
<% end %>
|
|
292
297
|
</head>
|
|
293
298
|
<body>
|
|
294
299
|
<div class="container">
|
|
@@ -310,7 +315,7 @@
|
|
|
310
315
|
<%= @time_range.first.strftime("%b %-e, %Y") %> to <%= @time_range.last.strftime("%b %-e, %Y") %>
|
|
311
316
|
</span>
|
|
312
317
|
<span class="text-muted"><%= @time_zone.name.sub(" (US & Canada)", "") %></span>
|
|
313
|
-
|
|
318
|
+
<%= javascript_tag nonce: true do %>
|
|
314
319
|
var startDate = <%= raw json_escape(@time_range.first.to_json) %>;
|
|
315
320
|
var endDate = <%= raw json_escape(@time_range.last.to_json) %>;
|
|
316
321
|
new Litepicker({
|
|
@@ -333,7 +338,7 @@
|
|
|
333
338
|
window.location.href = window.location.pathname + "?" + params.toString();
|
|
334
339
|
}
|
|
335
340
|
});
|
|
336
|
-
|
|
341
|
+
<% end %>
|
|
337
342
|
<% end %>
|
|
338
343
|
</div>
|
|
339
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}] %>
|
|
@@ -15,7 +15,8 @@
|
|
|
15
15
|
<td style="width: 35%; color: #5cb85c;">
|
|
16
16
|
<% if search.converted_at %>
|
|
17
17
|
<strong>✓</strong>
|
|
18
|
-
|
|
18
|
+
<% convertable = Searchjoy.multiple_conversions ? search.conversions.min_by(&:created_at)&.convertable : search.convertable %>
|
|
19
|
+
<%= convertable ? (Searchjoy.conversion_name ? Searchjoy.conversion_name.call(convertable) : "#{convertable.model_name.name} #{convertable.id}") : "Converted" %>
|
|
19
20
|
<% end %>
|
|
20
21
|
</td>
|
|
21
22
|
<td style="width: 20%;" class="num">
|
|
@@ -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);
|
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
function fetchRecentSearches() {
|
|
19
|
-
load(document.getElementById("stream"),
|
|
19
|
+
load(document.getElementById("stream"), <%= raw json_escape(searches_recent_path.to_json) %>)
|
|
20
20
|
setTimeout(fetchRecentSearches, 5 * 1000);
|
|
21
21
|
}
|
|
22
22
|
fetchRecentSearches();
|
|
23
|
-
|
|
23
|
+
<% end %>
|
|
@@ -7,12 +7,17 @@ class <%= migration_class_name %> < ActiveRecord::Migration<%= migration_version
|
|
|
7
7
|
t.string :normalized_query
|
|
8
8
|
t.integer :results_count
|
|
9
9
|
t.datetime :created_at
|
|
10
|
-
t.references :convertable, polymorphic: true, index: {name: "index_searchjoy_searches_on_convertable"}
|
|
11
10
|
t.datetime :converted_at
|
|
12
11
|
end
|
|
13
12
|
|
|
14
13
|
add_index :searchjoy_searches, [:created_at]
|
|
15
14
|
add_index :searchjoy_searches, [:search_type, :created_at]
|
|
16
15
|
add_index :searchjoy_searches, [:search_type, :normalized_query, :created_at], name: "index_searchjoy_searches_on_search_type_query" # autogenerated name is too long
|
|
16
|
+
|
|
17
|
+
create_table :searchjoy_conversions do |t|
|
|
18
|
+
t.references :search
|
|
19
|
+
t.references :convertable, polymorphic: true, index: {name: "index_searchjoy_conversions_on_convertable"}
|
|
20
|
+
t.datetime :created_at
|
|
21
|
+
end
|
|
17
22
|
end
|
|
18
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
|
|
@@ -23,15 +23,34 @@ module Searchjoy
|
|
|
23
23
|
mattr_accessor :query_name
|
|
24
24
|
mattr_accessor :query_url
|
|
25
25
|
|
|
26
|
+
# multiple conversions
|
|
27
|
+
mattr_accessor :multiple_conversions
|
|
28
|
+
self.multiple_conversions = true
|
|
29
|
+
|
|
26
30
|
def self.attach_to_searchkick!
|
|
27
31
|
Searchkick::Query.prepend(Searchjoy::Track::Query)
|
|
28
32
|
Searchkick::MultiSearch.prepend(Searchjoy::Track::MultiSearch)
|
|
29
33
|
Searchkick::Results.send(:attr_accessor, :search)
|
|
30
34
|
end
|
|
35
|
+
|
|
36
|
+
def self.backfill_conversions
|
|
37
|
+
Searchjoy::Search.where.not(converted_at: nil).left_joins(:conversions).where(searchjoy_conversions: {id: nil}).find_in_batches do |searches|
|
|
38
|
+
conversions =
|
|
39
|
+
searches.map do |search|
|
|
40
|
+
{
|
|
41
|
+
search_id: search.id,
|
|
42
|
+
convertable_id: search.convertable_id,
|
|
43
|
+
convertable_type: search.convertable_type,
|
|
44
|
+
created_at: search.converted_at
|
|
45
|
+
}
|
|
46
|
+
end
|
|
47
|
+
Searchjoy::Conversion.insert_all(conversions)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
31
50
|
end
|
|
32
51
|
|
|
33
52
|
if defined?(Rails)
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
Searchjoy.attach_to_searchkick!
|
|
53
|
+
require_relative "searchjoy/engine"
|
|
54
|
+
elsif defined?(Searchkick)
|
|
55
|
+
Searchjoy.attach_to_searchkick!
|
|
37
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:
|
|
4
|
+
version: 1.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Andrew Kane
|
|
8
|
-
autorequire:
|
|
8
|
+
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2023-02-08 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: chartkick
|
|
@@ -44,86 +44,16 @@ dependencies:
|
|
|
44
44
|
requirements:
|
|
45
45
|
- - ">="
|
|
46
46
|
- !ruby/object:Gem::Version
|
|
47
|
-
version: '
|
|
47
|
+
version: '6'
|
|
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: '
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
|
58
|
-
requirements:
|
|
59
|
-
- - ">="
|
|
60
|
-
- !ruby/object:Gem::Version
|
|
61
|
-
version: '0'
|
|
62
|
-
type: :development
|
|
63
|
-
prerelease: false
|
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
-
requirements:
|
|
66
|
-
- - ">="
|
|
67
|
-
- !ruby/object:Gem::Version
|
|
68
|
-
version: '0'
|
|
69
|
-
- !ruby/object:Gem::Dependency
|
|
70
|
-
name: rake
|
|
71
|
-
requirement: !ruby/object:Gem::Requirement
|
|
72
|
-
requirements:
|
|
73
|
-
- - ">="
|
|
74
|
-
- !ruby/object:Gem::Version
|
|
75
|
-
version: '0'
|
|
76
|
-
type: :development
|
|
77
|
-
prerelease: false
|
|
78
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
-
requirements:
|
|
80
|
-
- - ">="
|
|
81
|
-
- !ruby/object:Gem::Version
|
|
82
|
-
version: '0'
|
|
83
|
-
- !ruby/object:Gem::Dependency
|
|
84
|
-
name: minitest
|
|
85
|
-
requirement: !ruby/object:Gem::Requirement
|
|
86
|
-
requirements:
|
|
87
|
-
- - ">="
|
|
88
|
-
- !ruby/object:Gem::Version
|
|
89
|
-
version: '0'
|
|
90
|
-
type: :development
|
|
91
|
-
prerelease: false
|
|
92
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
93
|
-
requirements:
|
|
94
|
-
- - ">="
|
|
95
|
-
- !ruby/object:Gem::Version
|
|
96
|
-
version: '0'
|
|
97
|
-
- !ruby/object:Gem::Dependency
|
|
98
|
-
name: sqlite3
|
|
99
|
-
requirement: !ruby/object:Gem::Requirement
|
|
100
|
-
requirements:
|
|
101
|
-
- - ">="
|
|
102
|
-
- !ruby/object:Gem::Version
|
|
103
|
-
version: '0'
|
|
104
|
-
type: :development
|
|
105
|
-
prerelease: false
|
|
106
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
107
|
-
requirements:
|
|
108
|
-
- - ">="
|
|
109
|
-
- !ruby/object:Gem::Version
|
|
110
|
-
version: '0'
|
|
111
|
-
- !ruby/object:Gem::Dependency
|
|
112
|
-
name: searchkick
|
|
113
|
-
requirement: !ruby/object:Gem::Requirement
|
|
114
|
-
requirements:
|
|
115
|
-
- - ">="
|
|
116
|
-
- !ruby/object:Gem::Version
|
|
117
|
-
version: '0'
|
|
118
|
-
type: :development
|
|
119
|
-
prerelease: false
|
|
120
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
121
|
-
requirements:
|
|
122
|
-
- - ">="
|
|
123
|
-
- !ruby/object:Gem::Version
|
|
124
|
-
version: '0'
|
|
125
|
-
description:
|
|
126
|
-
email: andrew@chartkick.com
|
|
54
|
+
version: '6'
|
|
55
|
+
description:
|
|
56
|
+
email: andrew@ankane.org
|
|
127
57
|
executables: []
|
|
128
58
|
extensions: []
|
|
129
59
|
extra_rdoc_files: []
|
|
@@ -134,6 +64,7 @@ files:
|
|
|
134
64
|
- app/assets/javascripts/searchjoy/application.js
|
|
135
65
|
- app/assets/javascripts/searchjoy/litepicker.js
|
|
136
66
|
- app/controllers/searchjoy/searches_controller.rb
|
|
67
|
+
- app/models/searchjoy/conversion.rb
|
|
137
68
|
- app/models/searchjoy/search.rb
|
|
138
69
|
- app/views/layouts/searchjoy/application.html.erb
|
|
139
70
|
- app/views/searchjoy/searches/index.html.erb
|
|
@@ -152,7 +83,7 @@ homepage: https://github.com/ankane/searchjoy
|
|
|
152
83
|
licenses:
|
|
153
84
|
- MIT
|
|
154
85
|
metadata: {}
|
|
155
|
-
post_install_message:
|
|
86
|
+
post_install_message:
|
|
156
87
|
rdoc_options: []
|
|
157
88
|
require_paths:
|
|
158
89
|
- lib
|
|
@@ -160,15 +91,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
160
91
|
requirements:
|
|
161
92
|
- - ">="
|
|
162
93
|
- !ruby/object:Gem::Version
|
|
163
|
-
version: '2.
|
|
94
|
+
version: '2.7'
|
|
164
95
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
165
96
|
requirements:
|
|
166
97
|
- - ">="
|
|
167
98
|
- !ruby/object:Gem::Version
|
|
168
99
|
version: '0'
|
|
169
100
|
requirements: []
|
|
170
|
-
rubygems_version: 3.
|
|
171
|
-
signing_key:
|
|
101
|
+
rubygems_version: 3.4.6
|
|
102
|
+
signing_key:
|
|
172
103
|
specification_version: 4
|
|
173
104
|
summary: Search analytics made easy
|
|
174
105
|
test_files: []
|