solidus_seo 1.0.7 → 1.0.8
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/app/decorators/controllers/spree/orders_controller_decorator.rb +55 -0
- data/app/decorators/models/spree/product_decorator.rb +3 -9
- data/app/views/solidus_seo/_analytics.html.erb +3 -152
- data/app/views/solidus_seo/_facebook.html.erb +37 -0
- data/app/views/solidus_seo/_google-analytics.html.erb +40 -0
- data/app/views/solidus_seo/_google-tag-manager.html.erb +50 -0
- data/app/views/solidus_seo/_pinterest.html.erb +84 -0
- data/lib/generators/solidus_seo/install/install_generator.rb +1 -0
- data/lib/generators/solidus_seo/install/templates/replace_taxon_breadcrumbs_helper.html.erb.deface +5 -0
- data/lib/solidus_seo/engine.rb +2 -0
- data/lib/solidus_seo/helpers/base_helper.rb +26 -0
- data/lib/solidus_seo/jsonld/breadcrumbs.rb +2 -2
- data/lib/solidus_seo/jsonld/list.rb +1 -1
- data/lib/solidus_seo/meta_data_builder.rb +0 -1
- data/lib/solidus_seo/version.rb +1 -1
- data/spec/examples.txt +30 -28
- data/spec/features/add_to_cart_spec.rb +29 -0
- data/spec/features/checkout_complete_spec.rb +14 -17
- data/spec/features/product_page_spec.rb +17 -1
- data/spec/support/testing_helpers.rb +10 -6
- data/spec/system_helper.rb +9 -7
- metadata +10 -3
- data/app/decorators/helpers/spree/base_helper_decorator.rb +0 -39
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3626084993746b4fd03d1ac122e5e5fd15e2c425e24c09ff66e48c85a8f58fd8
|
4
|
+
data.tar.gz: dc2e82b2dae8291d44ef540c3085b5ccc85682819acb3c405308e33e879f987b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5523b7a476f2e1f0fb42ea23ca16c926ecbff1f6c32f65438d431bfcb55c4ad84bdb3a4599356235f949b1c7dbafdfb1289d7edd98222851bd2d9d8aa6309471
|
7
|
+
data.tar.gz: 8b63780e4f7d9619c0c48dfda3f026a39e0b193fcda651df108d3ef5f60cbcc873d21155f1355ead1eeb8d60ec5249c536b469ec88ee69c51835e67a1183ad62
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Spree
|
4
|
+
module OrdersControllerDecorator
|
5
|
+
def self.prepended(base)
|
6
|
+
base.class_eval do
|
7
|
+
around_action :calculate_cart_diff, only: :populate
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def calculate_cart_diff
|
14
|
+
previous_cart_items = order_contents_hash
|
15
|
+
|
16
|
+
yield
|
17
|
+
|
18
|
+
current_cart_items = order_contents_hash
|
19
|
+
|
20
|
+
cart_diff = current_cart_items.map do |variant_sku, quantity|
|
21
|
+
added_quantity = quantity - (previous_cart_items[variant_sku] || 0)
|
22
|
+
|
23
|
+
[variant_sku, added_quantity.positive? ? added_quantity : nil]
|
24
|
+
end.to_h.compact
|
25
|
+
|
26
|
+
cart_diff = cart_diff.map do |variant_sku, quantity|
|
27
|
+
variant = Spree::Variant.find_by(sku: variant_sku)
|
28
|
+
|
29
|
+
[
|
30
|
+
variant_sku,
|
31
|
+
{
|
32
|
+
id: variant.product.master.sku,
|
33
|
+
name: variant.product.name,
|
34
|
+
variant: variant.options_text,
|
35
|
+
price: variant.price,
|
36
|
+
quantity: quantity
|
37
|
+
}
|
38
|
+
]
|
39
|
+
end.to_h
|
40
|
+
|
41
|
+
flash[:added_to_cart] = cart_diff if cart_diff.present?
|
42
|
+
end
|
43
|
+
|
44
|
+
def order_contents_hash
|
45
|
+
return {} if current_order.blank?
|
46
|
+
|
47
|
+
current_order.line_items.each_with_object({}) do |li, acc|
|
48
|
+
acc[li.variant.sku] ||= 0
|
49
|
+
acc[li.variant.sku] += li.quantity
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
::Spree::StoreController.prepend(self)
|
54
|
+
end
|
55
|
+
end
|
@@ -40,14 +40,8 @@ module Spree
|
|
40
40
|
master.default_price.amount
|
41
41
|
end
|
42
42
|
|
43
|
-
def
|
44
|
-
|
45
|
-
arel_conditions = [
|
46
|
-
variants_including_master.arel_table[:track_inventory].eq(false),
|
47
|
-
Spree::StockItem.arel_table[:count_on_hand].gt(0)
|
48
|
-
]
|
49
|
-
in_stock_variants = variants_including_master.joins(:stock_items).where(arel_conditions.inject(:or))
|
50
|
-
in_stock_variants.any?
|
43
|
+
def in_stock?
|
44
|
+
available? && variants_including_master.suppliable.any?
|
51
45
|
end
|
52
46
|
|
53
47
|
def seo_data
|
@@ -98,7 +92,7 @@ module Spree
|
|
98
92
|
"priceCurrency": seo_currency,
|
99
93
|
"price": seo_price,
|
100
94
|
"itemCondition": "http://schema.org/NewCondition",
|
101
|
-
"availability": "http://schema.org/#{
|
95
|
+
"availability": "http://schema.org/#{ in_stock? ? 'InStock' : 'OutOfStock'}",
|
102
96
|
}
|
103
97
|
}
|
104
98
|
end
|
@@ -1,159 +1,10 @@
|
|
1
|
-
<%
|
2
|
-
just_purchased = @order && order_just_completed?(@order)
|
3
|
-
if ENV.values_at('GOOGLE_TAG_MANAGER_ID', 'GOOGLE_ANALYTICS_ID', 'FACEBOOK_PIXEL_ID', 'PINTEREST_TAG_ID').any? \
|
4
|
-
&& just_purchased
|
5
|
-
|
6
|
-
shared_order_data = {
|
7
|
-
affiliation: current_store.name,
|
8
|
-
currency: @order.currency,
|
9
|
-
tax: @order.tax_total,
|
10
|
-
shipping: @order.ship_total
|
11
|
-
}
|
12
|
-
|
13
|
-
purchased_items = @order.line_items.map do |line_item|
|
14
|
-
variant = line_item.variant
|
15
|
-
|
16
|
-
next unless variant
|
17
|
-
|
18
|
-
{
|
19
|
-
id: variant.sku,
|
20
|
-
name: variant.name,
|
21
|
-
price: line_item.total,
|
22
|
-
variant: variant.options_text,
|
23
|
-
quantity: line_item.quantity
|
24
|
-
}
|
25
|
-
end.compact
|
26
|
-
|
27
|
-
end %>
|
28
|
-
|
29
1
|
<script>
|
30
|
-
window.
|
2
|
+
window.solidusSeoDataLayer = function (tagName, eventName) {
|
31
3
|
var tag = document.querySelector('script[data-tag=' + tagName + ']');
|
32
|
-
if(!tag) return;
|
33
4
|
tag.dataset.firedEvents = eventName;
|
34
5
|
}
|
35
6
|
</script>
|
36
7
|
|
37
|
-
<%
|
38
|
-
|
39
|
-
<script type="text/javascript" data-tag="google-tag-manager">
|
40
|
-
window.dataLayer = window.dataLayer || [];
|
41
|
-
|
42
|
-
<% if just_purchased %>
|
43
|
-
let orderData = Object.assign({}, <%= raw shared_order_data.to_json %>, {
|
44
|
-
'id': '<%= j @order.number %>', // Transaction ID. Required for purchases and refunds.
|
45
|
-
'revenue': '<%= @order.total %>', // Total transaction value (incl. tax and shipping)
|
46
|
-
'coupon': '' // TODO: Add coupon code if present
|
47
|
-
});
|
48
|
-
|
49
|
-
window.dataLayer.push({
|
50
|
-
'ecommerce': {
|
51
|
-
'purchase': {
|
52
|
-
'actionField': orderData,
|
53
|
-
'products': <%= raw purchased_items.to_json %>
|
54
|
-
}
|
55
|
-
}
|
56
|
-
});
|
57
|
-
window.solidusSeoListener('google-tag-manager', 'purchase');
|
58
|
-
<% end %>
|
59
|
-
|
60
|
-
(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
|
61
|
-
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
|
62
|
-
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
|
63
|
-
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
|
64
|
-
})(window,document,'script','dataLayer','<%= ENV['GOOGLE_TAG_MANAGER_ID'] %>');
|
65
|
-
</script>
|
66
|
-
|
67
|
-
<% elsif ENV['GOOGLE_ANALYTICS_ID'].present? %>
|
68
|
-
|
69
|
-
<script async src="https://www.googletagmanager.com/gtag/js?id=<%= ENV['GOOGLE_ANALYTICS_ID'] %>"></script>
|
70
|
-
<script type="text/javascript" data-tag="google-analytics">
|
71
|
-
window.dataLayer = window.dataLayer || [];
|
72
|
-
function gtag(){ dataLayer.push(arguments); }
|
73
|
-
gtag('js', new Date());
|
74
|
-
gtag('config', '<%= ENV['GOOGLE_ANALYTICS_ID'] %>');
|
75
|
-
|
76
|
-
<% if just_purchased %>
|
77
|
-
let purchaseData = Object.assign({}, <%= raw shared_order_data.to_json %>, {
|
78
|
-
'transaction_id': '<%= @order.number %>',
|
79
|
-
'value': '<%= @order.total %>',
|
80
|
-
'items': <%= raw purchased_items.to_json %>
|
81
|
-
});
|
82
|
-
|
83
|
-
gtag('event', 'purchase', purchaseData);
|
84
|
-
window.solidusSeoListener('google-analytics', 'purchase');
|
85
|
-
<% end %>
|
86
|
-
</script>
|
87
|
-
<% end %>
|
88
|
-
|
89
|
-
<% if ENV['FACEBOOK_PIXEL_ID'].present? %>
|
90
|
-
<script type="text/javascript" data-tag="facebook">
|
91
|
-
!function(f,b,e,v,n,t,s) {
|
92
|
-
if (f.fbq) return;
|
93
|
-
n = f.fbq = function() { n.callMethod ? n.callMethod.apply(n, arguments) : n.queue.push(arguments) };
|
94
|
-
if (!f._fbq) f._fbq=n;
|
95
|
-
n.push = n; n.loaded = !0; n.version = '2.0'; n.queue=[]; t = b.createElement(e); t.async = !0; t.src = v;
|
96
|
-
s = b.getElementsByTagName(e)[0]; s.parentNode.insertBefore(t, s);
|
97
|
-
}(window, document,'script', 'https://connect.facebook.net/en_US/fbevents.js');
|
98
|
-
|
99
|
-
fbq('init', '<%= ENV['FACEBOOK_PIXEL_ID'] %>');
|
100
|
-
fbq('track', 'PageView');
|
101
|
-
|
102
|
-
<% if just_purchased %>
|
103
|
-
<% items = purchased_items.map { |li| li.slice(:id, :quantity) } %>
|
104
|
-
|
105
|
-
fbq('track', 'Purchase', {
|
106
|
-
value: <%= @order.total %>,
|
107
|
-
currency: 'USD',
|
108
|
-
contents: <%= raw items.to_json %>,
|
109
|
-
content_type: 'product',
|
110
|
-
|
111
|
-
// custom properties
|
112
|
-
order_number: '<%= @order.number %>',
|
113
|
-
item_total: <%= @order.item_total %>,
|
114
|
-
tax_total: <%= @order.tax_total %>,
|
115
|
-
ship_total: <%= @order.ship_total %>,
|
116
|
-
promo_total: <%= @order.promo_total %>,
|
117
|
-
});
|
118
|
-
window.solidusSeoListener('facebook', 'purchase');
|
119
|
-
<% end %>
|
120
|
-
</script>
|
121
|
-
<noscript>
|
122
|
-
<img height="1" width="1" src="https://www.facebook.com/tr?id=<%= ENV['FACEBOOK_PIXEL_ID'] %>&ev=PageView&noscript=1" />
|
123
|
-
</noscript>
|
124
|
-
<% end %>
|
125
|
-
|
126
|
-
<% if ENV['PINTEREST_TAG_ID'].present? %>
|
127
|
-
<script type="text/javascript" data-tag="pinterest">
|
128
|
-
!function(e){if(!window.pintrk){window.pintrk=function(){window.pintrk.queue.push(
|
129
|
-
Array.prototype.slice.call(arguments))};var
|
130
|
-
n=window.pintrk;n.queue=[],n.version="3.0";var
|
131
|
-
t=document.createElement("script");t.async=!0,t.src=e;var
|
132
|
-
r=document.getElementsByTagName("script")[0];r.parentNode.insertBefore(t,r)}}("https://s.pinimg.com/ct/core.js");
|
133
|
-
pintrk('load', '<%= ENV['PINTEREST_TAG_ID'] %>');
|
134
|
-
pintrk('page');
|
135
|
-
|
136
|
-
<% if just_purchased %>
|
137
|
-
<% items = purchased_items.map do |li|
|
138
|
-
{
|
139
|
-
product_id: li[:id],
|
140
|
-
product_name: li[:name],
|
141
|
-
product_quantity: li[:quantity],
|
142
|
-
product_price: li[:price],
|
143
|
-
}
|
144
|
-
end %>
|
145
|
-
|
146
|
-
pintrk('track', 'checkout', {
|
147
|
-
value: <%= @order.total %>,
|
148
|
-
order_quantity: <%= @order.line_items.sum(&:quantity) %>,
|
149
|
-
currency: 'USD',
|
150
|
-
line_items: <%= raw items.to_json %>
|
151
|
-
});
|
152
|
-
|
153
|
-
window.solidusSeoListener('pinterest', 'purchase');
|
154
|
-
<% end %>
|
155
|
-
</script>
|
156
|
-
<noscript>
|
157
|
-
<img height="1" width="1" style="display:none;" alt="" src="https://ct.pinterest.com/v3/?tid=<%= ENV['PINTEREST_TAG_ID'] %>&event=init&noscript=1" />
|
158
|
-
</noscript>
|
8
|
+
<% %w[google-tag-manager google-analytics facebook pinterest].each do |tag_name| %>
|
9
|
+
<%= render "solidus_seo/#{tag_name}", just_purchased: (@order && order_just_completed?(@order)), order: @order %>
|
159
10
|
<% end %>
|
@@ -0,0 +1,37 @@
|
|
1
|
+
<%
|
2
|
+
return if ENV['FACEBOOK_PIXEL_ID'].blank?
|
3
|
+
|
4
|
+
if just_purchased
|
5
|
+
order_data = {
|
6
|
+
value: order.total,
|
7
|
+
currency: order.currency,
|
8
|
+
content_type: 'product',
|
9
|
+
contents: order.line_items.map do |line_item|
|
10
|
+
next unless line_item.variant
|
11
|
+
|
12
|
+
{ id: line_item.variant.sku, quantity: line_item.quantity }
|
13
|
+
end.compact,
|
14
|
+
|
15
|
+
# custom properties
|
16
|
+
order_number: order.number,
|
17
|
+
item_total: order.item_total,
|
18
|
+
tax_total: order.tax_total,
|
19
|
+
ship_total: order.ship_total,
|
20
|
+
promo_total: order.promo_total
|
21
|
+
}
|
22
|
+
end
|
23
|
+
%>
|
24
|
+
<script type="text/javascript" data-tag="facebook">
|
25
|
+
!function(f,b,e,v,n,t,s) {if (f.fbq) return;n = f.fbq = function() { n.callMethod ? n.callMethod.apply(n, arguments) : n.queue.push(arguments) };if (!f._fbq) f._fbq=n;n.push = n; n.loaded = !0; n.version = '2.0'; n.queue=[]; t = b.createElement(e); t.async = !0; t.src = v;s = b.getElementsByTagName(e)[0]; s.parentNode.insertBefore(t, s);}(window, document,'script', 'https://connect.facebook.net/en_US/fbevents.js');
|
26
|
+
|
27
|
+
fbq('init', '<%= ENV['FACEBOOK_PIXEL_ID'] %>');
|
28
|
+
fbq('track', 'PageView');
|
29
|
+
|
30
|
+
<% if just_purchased %>
|
31
|
+
fbq('track', 'Purchase', <%== order_data.to_json %>);
|
32
|
+
window.solidusSeoDataLayer('facebook', 'purchase');
|
33
|
+
<% end %>
|
34
|
+
</script>
|
35
|
+
<noscript>
|
36
|
+
<img height="1" width="1" src="https://www.facebook.com/tr?id=<%= ENV['FACEBOOK_PIXEL_ID'] %>&ev=PageView&noscript=1" />
|
37
|
+
</noscript>
|
@@ -0,0 +1,40 @@
|
|
1
|
+
<%
|
2
|
+
return if ENV['GOOGLE_TAG_MANAGER_ID'].present? || ENV['GOOGLE_ANALYTICS_ID'].blank?
|
3
|
+
|
4
|
+
if just_purchased
|
5
|
+
order_data = {
|
6
|
+
transaction_id: order.number,
|
7
|
+
value: order.total,
|
8
|
+
items: order.line_items.map do |line_item|
|
9
|
+
next unless line_item.variant
|
10
|
+
|
11
|
+
{
|
12
|
+
id: line_item.variant.sku,
|
13
|
+
name: line_item.variant.name,
|
14
|
+
price: line_item.price,
|
15
|
+
variant: line_item.variant.options_text,
|
16
|
+
quantity: line_item.quantity
|
17
|
+
}
|
18
|
+
end.compact,
|
19
|
+
|
20
|
+
affiliation: current_store.name,
|
21
|
+
currency: order.currency,
|
22
|
+
tax: order.tax_total,
|
23
|
+
shipping: order.ship_total
|
24
|
+
}
|
25
|
+
end
|
26
|
+
%>
|
27
|
+
<script async src="https://www.googletagmanager.com/gtag/js?id=<%= ENV['GOOGLE_ANALYTICS_ID'] %>"></script>
|
28
|
+
<script type="text/javascript" data-tag="google-analytics">
|
29
|
+
window.dataLayer = window.dataLayer || [];
|
30
|
+
|
31
|
+
function gtag(){ dataLayer.push(arguments); }
|
32
|
+
|
33
|
+
gtag('js', new Date());
|
34
|
+
gtag('config', '<%= ENV['GOOGLE_ANALYTICS_ID'] %>');
|
35
|
+
|
36
|
+
<% if just_purchased %>
|
37
|
+
gtag('event', 'purchase', <%== order_data.to_json %>);
|
38
|
+
window.solidusSeoDataLayer('google-analytics', 'purchase');
|
39
|
+
<% end %>
|
40
|
+
</script>
|
@@ -0,0 +1,50 @@
|
|
1
|
+
<%
|
2
|
+
return if ENV['GOOGLE_ANALYTICS_ID'].present? || ENV['GOOGLE_TAG_MANAGER_ID'].blank?
|
3
|
+
|
4
|
+
if just_purchased
|
5
|
+
order_data = {
|
6
|
+
id: order.number,
|
7
|
+
revenue: order.total,
|
8
|
+
coupon: '', # TODO: Add coupon code if present
|
9
|
+
|
10
|
+
affiliation: current_store.name,
|
11
|
+
currency: order.currency,
|
12
|
+
tax: order.tax_total,
|
13
|
+
shipping: order.ship_total
|
14
|
+
}
|
15
|
+
|
16
|
+
purchased_items = order.line_items.map do |line_item|
|
17
|
+
next unless line_item.variant
|
18
|
+
|
19
|
+
{
|
20
|
+
id: line_item.variant.sku,
|
21
|
+
name: line_item.variant.name,
|
22
|
+
price: line_item.total,
|
23
|
+
variant: line_item.variant.options_text,
|
24
|
+
quantity: line_item.quantity
|
25
|
+
}
|
26
|
+
end.compact
|
27
|
+
end
|
28
|
+
%>
|
29
|
+
<script type="text/javascript" data-tag="google-tag-manager">
|
30
|
+
window.dataLayer = window.dataLayer || [];
|
31
|
+
|
32
|
+
<% if just_purchased %>
|
33
|
+
window.dataLayer.push({
|
34
|
+
'ecommerce': {
|
35
|
+
'purchase': {
|
36
|
+
'actionField': <%== order_data.to_json %>,
|
37
|
+
'products': <%== purchased_items.to_json %>
|
38
|
+
}
|
39
|
+
}
|
40
|
+
});
|
41
|
+
|
42
|
+
window.solidusSeoDataLayer('google-tag-manager', 'purchase');
|
43
|
+
<% end %>
|
44
|
+
|
45
|
+
(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
|
46
|
+
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
|
47
|
+
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
|
48
|
+
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
|
49
|
+
})(window,document,'script','dataLayer','<%= ENV['GOOGLE_TAG_MANAGER_ID'] %>');
|
50
|
+
</script>
|
@@ -0,0 +1,84 @@
|
|
1
|
+
<%
|
2
|
+
return if ENV['PINTEREST_TAG_ID'].blank?
|
3
|
+
|
4
|
+
product_data = {}
|
5
|
+
add_to_cart_data = {}
|
6
|
+
order_data = {}
|
7
|
+
em_data = {}
|
8
|
+
|
9
|
+
user_email = current_order&.email || try_spree_current_user&.email
|
10
|
+
if user_email.present?
|
11
|
+
em_data = { em: user_email }
|
12
|
+
end
|
13
|
+
|
14
|
+
if just_purchased
|
15
|
+
order_data = {
|
16
|
+
value: order.total,
|
17
|
+
currency: order.currency,
|
18
|
+
order_quantity: order.line_items.sum(&:quantity),
|
19
|
+
line_items: order.line_items.map do |line_item|
|
20
|
+
next unless line_item.variant
|
21
|
+
|
22
|
+
{
|
23
|
+
product_id: line_item.variant.product.master.sku,
|
24
|
+
product_name: line_item.variant.name,
|
25
|
+
product_variant_id: line_item.variant.sku,
|
26
|
+
product_variant: line_item.variant.options_text,
|
27
|
+
product_quantity: line_item.quantity,
|
28
|
+
product_price: line_item.price
|
29
|
+
}
|
30
|
+
end.compact
|
31
|
+
}
|
32
|
+
end
|
33
|
+
|
34
|
+
if @product
|
35
|
+
product_data = {
|
36
|
+
line_items: [
|
37
|
+
{
|
38
|
+
product_name: @product.name,
|
39
|
+
product_id: @product.master.sku
|
40
|
+
}
|
41
|
+
]
|
42
|
+
}
|
43
|
+
end
|
44
|
+
|
45
|
+
if flash[:added_to_cart].present?
|
46
|
+
add_to_cart_data = {
|
47
|
+
value: order.total,
|
48
|
+
currency: order.currency,
|
49
|
+
order_id: order.number,
|
50
|
+
line_items: flash[:added_to_cart].map do |variant_sku, variant|
|
51
|
+
{
|
52
|
+
product_id: variant['id'],
|
53
|
+
product_name: variant['name'],
|
54
|
+
product_variant_id: variant_sku,
|
55
|
+
product_variant: variant['variant'],
|
56
|
+
product_price: variant['price'],
|
57
|
+
product_quantity: variant['quantity']
|
58
|
+
}
|
59
|
+
end
|
60
|
+
}
|
61
|
+
end
|
62
|
+
%>
|
63
|
+
<script type="text/javascript" data-tag="pinterest">
|
64
|
+
!function(e){if(!window.pintrk){window.pintrk=function(){window.pintrk.queue.push(Array.prototype.slice.call(arguments))};var n=window.pintrk;n.queue=[],n.version="3.0";var t=document.createElement("script");t.async=!0,t.src=e;var r=document.getElementsByTagName("script")[0];r.parentNode.insertBefore(t,r)}}("https://s.pinimg.com/ct/core.js");
|
65
|
+
|
66
|
+
pintrk('load', '<%= ENV['PINTEREST_TAG_ID'] %>' <%== em_data.present? ? ", #{em_data.to_json}" : '' %>);
|
67
|
+
pintrk('page');
|
68
|
+
|
69
|
+
pintrk('track', 'pagevisit'<%== product_data.present? ? ", #{product_data.to_json}" : '' %>);
|
70
|
+
window.solidusSeoDataLayer('pinterest', 'pagevisit');
|
71
|
+
|
72
|
+
<% if add_to_cart_data.present? %>
|
73
|
+
pintrk('track', 'addtocart', <%== add_to_cart_data.to_json %>);
|
74
|
+
window.solidusSeoDataLayer('pinterest', 'addtocart');
|
75
|
+
<% end %>
|
76
|
+
|
77
|
+
<% if order_data.present? %>
|
78
|
+
pintrk('track', 'checkout', <%== order_data.to_json %>);
|
79
|
+
window.solidusSeoDataLayer('pinterest', 'purchase');
|
80
|
+
<% end %>
|
81
|
+
</script>
|
82
|
+
<noscript>
|
83
|
+
<img height="1" width="1" style="display:none;" alt="" src="https://ct.pinterest.com/v3/?tid=<%= ENV['PINTEREST_TAG_ID'] %>&event=init&noscript=1" />
|
84
|
+
</noscript>
|
@@ -34,6 +34,7 @@ module SolidusSeo
|
|
34
34
|
copy_file 'remove_original_title_tag.deface', 'app/overrides/spree/shared/_head/remove_original_title_tag.deface'
|
35
35
|
copy_file 'insert_product_list_helper.html.erb.deface', 'app/overrides/spree/shared/_products/insert_product_list_helper.html.erb.deface'
|
36
36
|
copy_file 'insert_analytics_in_layout.html.erb.deface', 'app/overrides/spree/layouts/spree_application/insert_analytics_in_layout.html.erb.deface'
|
37
|
+
copy_file 'replace_taxon_breadcrumbs_helper.html.erb.deface', 'app/overrides/spree/layouts/spree_application/replace_taxon_breadcrumbs_helper.html.erb.deface'
|
37
38
|
end
|
38
39
|
end
|
39
40
|
end
|
data/lib/solidus_seo/engine.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
require_dependency 'solidus_seo/jsonld/tag_helper'
|
3
|
+
require_dependency 'solidus_seo/helpers/base_helper'
|
3
4
|
|
4
5
|
module SolidusSeo
|
5
6
|
class Engine < Rails::Engine
|
@@ -21,6 +22,7 @@ module SolidusSeo
|
|
21
22
|
initializer "solidus_seo.view_helpers" do
|
22
23
|
ActiveSupport.on_load(:action_view) do
|
23
24
|
ActionView::Base.send :include, ::SolidusSeo::Jsonld::TagHelper
|
25
|
+
ActionView::Base.send :include, ::SolidusSeo::Helpers::BaseHelper
|
24
26
|
end
|
25
27
|
end
|
26
28
|
|
@@ -4,6 +4,32 @@ module SolidusSeo
|
|
4
4
|
def plain_text(text)
|
5
5
|
ActionController::Base.helpers.strip_tags(text.to_s).gsub(/\s+/, ' ')
|
6
6
|
end
|
7
|
+
|
8
|
+
def breadcrumb_pairs(taxon)
|
9
|
+
crumbs = []
|
10
|
+
|
11
|
+
if taxon
|
12
|
+
crumbs << [Spree.t(:products), products_url]
|
13
|
+
crumbs += taxon.ancestors.collect { |a| [a.name, spree.nested_taxons_url(a.permalink)] } unless taxon.ancestors.empty?
|
14
|
+
crumbs << [taxon.name, spree.nested_taxons_url(taxon.permalink)]
|
15
|
+
else
|
16
|
+
crumbs << [Spree.t(:products), products_url]
|
17
|
+
end
|
18
|
+
|
19
|
+
crumbs
|
20
|
+
end
|
21
|
+
|
22
|
+
def taxon_breadcrumbs_jsonld(taxon, separator = ' » ', list_class = 'list-inline', list_item_class = 'list-inline-item')
|
23
|
+
return '' if current_page?('/') || taxon.nil?
|
24
|
+
|
25
|
+
separator = tag.span(separator.html_safe, class: 'breadcrumb-separator')
|
26
|
+
original_output = Nokogiri::HTML::DocumentFragment.parse(taxon_breadcrumbs(taxon, separator, list_class).to_s)
|
27
|
+
original_output.xpath('@itemscope|@itemtype|@itemprop|.//@itemscope|.//@itemtype|.//@itemprop').remove
|
28
|
+
original_output.search('.columns').first['class'] = ''
|
29
|
+
original_output.search('li').attr('class', list_item_class)
|
30
|
+
|
31
|
+
jsonld_breadcrumbs(breadcrumb_pairs(taxon)) + original_output.to_s.html_safe
|
32
|
+
end
|
7
33
|
end
|
8
34
|
end
|
9
35
|
end
|
@@ -2,7 +2,7 @@ require_dependency 'solidus_seo/jsonld/list'
|
|
2
2
|
|
3
3
|
module SolidusSeo
|
4
4
|
module Jsonld
|
5
|
-
class Breadcrumbs < List
|
5
|
+
class Breadcrumbs < SolidusSeo::Jsonld::List
|
6
6
|
private
|
7
7
|
|
8
8
|
def list_type
|
@@ -15,7 +15,7 @@ module SolidusSeo
|
|
15
15
|
|
16
16
|
def as_list_item(item)
|
17
17
|
# `item` in the form of [text, url]
|
18
|
-
breadcrumb_text, breadcrumb_url =
|
18
|
+
breadcrumb_text, breadcrumb_url = item
|
19
19
|
|
20
20
|
{
|
21
21
|
'@type': 'ListItem',
|
data/lib/solidus_seo/version.rb
CHANGED
data/spec/examples.txt
CHANGED
@@ -1,30 +1,32 @@
|
|
1
1
|
example_id | status | run_time |
|
2
2
|
------------------------------------------------ | ------ | --------------- |
|
3
|
-
./spec/features/
|
4
|
-
./spec/features/checkout_complete_spec.rb[1:
|
5
|
-
./spec/features/checkout_complete_spec.rb[1:
|
6
|
-
./spec/features/checkout_complete_spec.rb[1:
|
7
|
-
./spec/features/
|
8
|
-
./spec/features/homepage_spec.rb[1:1:
|
9
|
-
./spec/features/homepage_spec.rb[1:2
|
10
|
-
./spec/features/homepage_spec.rb[1:2:
|
11
|
-
./spec/features/homepage_spec.rb[1:
|
12
|
-
./spec/features/homepage_spec.rb[1:3:
|
13
|
-
./spec/features/
|
14
|
-
./spec/features/product_page_spec.rb[1:1:
|
15
|
-
./spec/features/product_page_spec.rb[1:1:
|
16
|
-
./spec/features/product_page_spec.rb[1:
|
17
|
-
./spec/features/product_page_spec.rb[1:2:
|
18
|
-
./spec/features/product_page_spec.rb[1:2:
|
19
|
-
./spec/features/product_page_spec.rb[1:3:1]
|
20
|
-
./spec/features/product_page_spec.rb[1:3:
|
21
|
-
./spec/features/product_page_spec.rb[1:3:
|
22
|
-
./spec/features/
|
23
|
-
./spec/features/
|
24
|
-
./spec/features/taxon_page_spec.rb[1:1:
|
25
|
-
./spec/features/taxon_page_spec.rb[1:2
|
26
|
-
./spec/features/taxon_page_spec.rb[1:
|
27
|
-
./spec/features/taxon_page_spec.rb[1:2:
|
28
|
-
./spec/features/taxon_page_spec.rb[1:
|
29
|
-
./spec/features/taxon_page_spec.rb[1:3:
|
30
|
-
./spec/features/taxon_page_spec.rb[1:
|
3
|
+
./spec/features/add_to_cart_spec.rb[1:1:1] | passed | 1.6 seconds |
|
4
|
+
./spec/features/checkout_complete_spec.rb[1:1:1] | passed | 0.65012 seconds |
|
5
|
+
./spec/features/checkout_complete_spec.rb[1:2:1] | passed | 0.56665 seconds |
|
6
|
+
./spec/features/checkout_complete_spec.rb[1:3:1] | passed | 0.66929 seconds |
|
7
|
+
./spec/features/checkout_complete_spec.rb[1:4:1] | passed | 0.44838 seconds |
|
8
|
+
./spec/features/homepage_spec.rb[1:1:1] | passed | 2.3 seconds |
|
9
|
+
./spec/features/homepage_spec.rb[1:1:2] | passed | 0.22388 seconds |
|
10
|
+
./spec/features/homepage_spec.rb[1:2:1] | passed | 0.2209 seconds |
|
11
|
+
./spec/features/homepage_spec.rb[1:2:2] | passed | 0.18137 seconds |
|
12
|
+
./spec/features/homepage_spec.rb[1:3:1] | passed | 0.20727 seconds |
|
13
|
+
./spec/features/homepage_spec.rb[1:3:2] | passed | 0.20346 seconds |
|
14
|
+
./spec/features/product_page_spec.rb[1:1:1] | passed | 0.29118 seconds |
|
15
|
+
./spec/features/product_page_spec.rb[1:1:2] | passed | 0.30857 seconds |
|
16
|
+
./spec/features/product_page_spec.rb[1:1:3] | passed | 0.28452 seconds |
|
17
|
+
./spec/features/product_page_spec.rb[1:2:1] | passed | 0.47017 seconds |
|
18
|
+
./spec/features/product_page_spec.rb[1:2:2:1] | passed | 0.3369 seconds |
|
19
|
+
./spec/features/product_page_spec.rb[1:2:3:1] | passed | 0.37361 seconds |
|
20
|
+
./spec/features/product_page_spec.rb[1:3:1] | passed | 0.33857 seconds |
|
21
|
+
./spec/features/product_page_spec.rb[1:3:2] | passed | 0.29488 seconds |
|
22
|
+
./spec/features/product_page_spec.rb[1:3:3] | passed | 0.26324 seconds |
|
23
|
+
./spec/features/product_page_spec.rb[1:4:1:1] | passed | 0.4502 seconds |
|
24
|
+
./spec/features/taxon_page_spec.rb[1:1:1] | passed | 1.04 seconds |
|
25
|
+
./spec/features/taxon_page_spec.rb[1:1:2] | passed | 0.31403 seconds |
|
26
|
+
./spec/features/taxon_page_spec.rb[1:1:3] | passed | 0.30921 seconds |
|
27
|
+
./spec/features/taxon_page_spec.rb[1:2:1] | passed | 0.32058 seconds |
|
28
|
+
./spec/features/taxon_page_spec.rb[1:2:2:1] | passed | 0.30031 seconds |
|
29
|
+
./spec/features/taxon_page_spec.rb[1:2:3:1] | passed | 0.31003 seconds |
|
30
|
+
./spec/features/taxon_page_spec.rb[1:3:1] | passed | 0.30324 seconds |
|
31
|
+
./spec/features/taxon_page_spec.rb[1:3:2] | passed | 0.3043 seconds |
|
32
|
+
./spec/features/taxon_page_spec.rb[1:4:1] | passed | 0.5174 seconds |
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
describe 'Add to cart', type: :system do
|
4
|
+
let!(:store) { Spree::Store.default }
|
5
|
+
let!(:order) { create :completed_order_with_totals }
|
6
|
+
let!(:line_item) { order.line_items.first }
|
7
|
+
|
8
|
+
stub_authorization!
|
9
|
+
|
10
|
+
before do
|
11
|
+
current_order_stubs(order)
|
12
|
+
stub_const 'ENV', ENV.to_h.merge(env_variable => 'XXX-YYYYY')
|
13
|
+
|
14
|
+
visit spree.product_path(line_item.product)
|
15
|
+
find('#add-to-cart-button').click
|
16
|
+
end
|
17
|
+
|
18
|
+
context 'when PINTEREST_TAG_ID environment variable is present' do
|
19
|
+
let(:env_variable) { 'PINTEREST_TAG_ID' }
|
20
|
+
|
21
|
+
it 'tracks "add to cart" event' do
|
22
|
+
expect(page).to track_analytics_event :pinterest, 'addtocart', [
|
23
|
+
'track', 'addtocart', order.total, order.number, line_item.variant.product.master.sku,
|
24
|
+
line_item.name, line_item.variant.sku, line_item.variant.price
|
25
|
+
]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
@@ -1,14 +1,17 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
describe 'Checkout complete', type: :system do
|
2
4
|
let!(:store) { Spree::Store.default }
|
3
5
|
let!(:taxon) { create :taxon, name: 'MyTaxon' }
|
4
6
|
let!(:order) { create :completed_order_with_totals }
|
5
7
|
let!(:line_item) { order.line_items.first }
|
6
|
-
|
8
|
+
|
9
|
+
stub_authorization!
|
7
10
|
|
8
11
|
subject { visit spree.order_path(order) }
|
9
12
|
|
10
13
|
before do
|
11
|
-
|
14
|
+
current_order_stubs(order)
|
12
15
|
stub_const 'ENV', ENV.to_h.merge(env_variable => 'XXX-YYYYY')
|
13
16
|
allow_any_instance_of(Spree::OrdersHelper).to receive(:order_just_completed?).with(order) { true }
|
14
17
|
end
|
@@ -18,8 +21,7 @@ describe "Checkout complete", type: :system do
|
|
18
21
|
|
19
22
|
it 'includes and executes a purchase event script' do
|
20
23
|
subject
|
21
|
-
|
22
|
-
expect(page).to matcher_for 'google-tag-manager', [order.number, order.total, 'ecommerce', 'purchase', line_item.sku, line_item.total]
|
24
|
+
expect(page).to track_analytics_event 'google-tag-manager', 'purchase', ['ecommerce', 'purchase', order.number, order.total, line_item.sku]
|
23
25
|
end
|
24
26
|
end
|
25
27
|
|
@@ -28,7 +30,11 @@ describe "Checkout complete", type: :system do
|
|
28
30
|
|
29
31
|
it 'includes and executes a purchase event script' do
|
30
32
|
subject
|
31
|
-
expect(page).to
|
33
|
+
expect(page).to track_analytics_event 'google-analytics', 'purchase', [
|
34
|
+
'event', 'purchase', 'transaction_id', order.number,
|
35
|
+
order.total, line_item.sku, line_item.variant.name,
|
36
|
+
line_item.price, line_item.variant.options_text
|
37
|
+
]
|
32
38
|
end
|
33
39
|
end
|
34
40
|
|
@@ -37,7 +43,7 @@ describe "Checkout complete", type: :system do
|
|
37
43
|
|
38
44
|
it 'includes and executes a purchase event script' do
|
39
45
|
subject
|
40
|
-
expect(page).to
|
46
|
+
expect(page).to track_analytics_event :facebook, 'purchase', ['track', 'Purchase', order.total, line_item.sku, line_item.quantity, order.number]
|
41
47
|
end
|
42
48
|
end
|
43
49
|
|
@@ -46,16 +52,7 @@ describe "Checkout complete", type: :system do
|
|
46
52
|
|
47
53
|
it 'includes and executes a purchase event script' do
|
48
54
|
subject
|
49
|
-
expect(page).to
|
55
|
+
expect(page).to track_analytics_event :pinterest, 'purchase', ['track', 'checkout', order.total, line_item.sku, line_item.name, line_item.price]
|
50
56
|
end
|
51
57
|
end
|
52
58
|
end
|
53
|
-
|
54
|
-
# Builds a regex matcher for script tag contents
|
55
|
-
# @param tag_name [String] Value of script's data-tag attribute
|
56
|
-
# @param matches [Array] Keywords that must appear in script contents (order matters!)
|
57
|
-
# @return [Object] Returns a capybara matcher for a script tag with specific attributes and contents
|
58
|
-
def matcher_for(tag_name, matches)
|
59
|
-
matches = matches.flatten.map {|v| Regexp.escape(v.to_s) }.join('.+')
|
60
|
-
have_selector :css, "script[data-tag=#{tag_name}][data-fired-events=purchase]", visible: false, text: /#{matches}/i
|
61
|
-
end
|
@@ -26,7 +26,6 @@ describe "Product page", type: :system do
|
|
26
26
|
|
27
27
|
subject { visit spree.product_path(product) }
|
28
28
|
|
29
|
-
|
30
29
|
context 'jsonld markup output' do
|
31
30
|
it "contains 'Store' entity type" do
|
32
31
|
subject
|
@@ -92,4 +91,21 @@ describe "Product page", type: :system do
|
|
92
91
|
expect(page).to have_css "meta[property='product:price:amount'][content='#{seo_price}']", visible: false
|
93
92
|
end
|
94
93
|
end
|
94
|
+
|
95
|
+
context 'analytics event tracking' do
|
96
|
+
before do
|
97
|
+
stub_const 'ENV', ENV.to_h.merge(env_variable => 'XXX-YYYYY')
|
98
|
+
end
|
99
|
+
|
100
|
+
context 'when PINTEREST_TAG_ID environment variable is present' do
|
101
|
+
let(:env_variable) { 'PINTEREST_TAG_ID' }
|
102
|
+
|
103
|
+
it 'tracks "pagevisit" event with product data' do
|
104
|
+
subject
|
105
|
+
expect(page).to track_analytics_event :pinterest, 'pagevisit', [
|
106
|
+
'track', 'pagevisit', product.name, product.master.sku
|
107
|
+
]
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
95
111
|
end
|
@@ -10,13 +10,17 @@ module TestingHelpers
|
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
13
|
-
def
|
14
|
-
user ||= order.user
|
13
|
+
def current_order_stubs(order)
|
15
14
|
allow_any_instance_of(Spree::CheckoutController).to receive_messages(current_order: order)
|
15
|
+
allow_any_instance_of(Spree::OrdersController).to receive_messages(current_order: order)
|
16
|
+
end
|
16
17
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
18
|
+
# Builds a regex matcher for script tag contents
|
19
|
+
# @param tag_name [String] Value of script's data-tag attribute
|
20
|
+
# @param matches [Array] Keywords that must appear in script contents (order matters!)
|
21
|
+
# @return [Object] Returns a capybara matcher for a script tag with specific attributes and contents
|
22
|
+
def track_analytics_event(tag_name, event_name, matches)
|
23
|
+
matches = matches.flatten.map {|v| Regexp.escape(v.to_s) }.join('.+')
|
24
|
+
have_selector :css, "script[data-tag=#{tag_name}][data-fired-events=#{event_name}]", visible: false, text: /#{matches}/i
|
21
25
|
end
|
22
26
|
end
|
data/spec/system_helper.rb
CHANGED
@@ -1,15 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
RSpec.configure do |
|
3
|
-
|
4
|
-
|
2
|
+
RSpec.configure do |c|
|
3
|
+
Capybara.disable_animation = true
|
4
|
+
|
5
|
+
c.before(:example, type: :system) do
|
6
|
+
driven_by ENV['DEBUG_CAPYBARA'] ? :selenium_chrome : :selenium_chrome_headless
|
7
|
+
end
|
8
|
+
|
9
|
+
c.when_first_matching_example_defined(type: :system) do
|
10
|
+
c.before :suite do
|
5
11
|
# Preload assets
|
6
12
|
if Rails.application.respond_to?(:precompiled_assets)
|
7
13
|
Rails.application.precompiled_assets
|
8
14
|
end
|
9
15
|
end
|
10
|
-
|
11
|
-
config.before(:example, type: :system) do
|
12
|
-
driven_by :apparition
|
13
|
-
end
|
14
16
|
end
|
15
17
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: solidus_seo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Karma Creative
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-01-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: solidus_core
|
@@ -337,12 +337,16 @@ files:
|
|
337
337
|
- app/assets/javascripts/spree/frontend/solidus_seo.js
|
338
338
|
- app/assets/stylesheets/spree/backend/solidus_seo.css
|
339
339
|
- app/assets/stylesheets/spree/frontend/solidus_seo.css
|
340
|
+
- app/decorators/controllers/spree/orders_controller_decorator.rb
|
340
341
|
- app/decorators/controllers/spree/store_controller_decorator.rb
|
341
|
-
- app/decorators/helpers/spree/base_helper_decorator.rb
|
342
342
|
- app/decorators/helpers/spree/core/controller_helpers/common_decorator.rb
|
343
343
|
- app/decorators/models/spree/product_decorator.rb
|
344
344
|
- app/decorators/models/spree/store_decorator.rb
|
345
345
|
- app/views/solidus_seo/_analytics.html.erb
|
346
|
+
- app/views/solidus_seo/_facebook.html.erb
|
347
|
+
- app/views/solidus_seo/_google-analytics.html.erb
|
348
|
+
- app/views/solidus_seo/_google-tag-manager.html.erb
|
349
|
+
- app/views/solidus_seo/_pinterest.html.erb
|
346
350
|
- config/locales/en.yml
|
347
351
|
- config/routes.rb
|
348
352
|
- lib/generators/solidus_seo/install/install_generator.rb
|
@@ -354,6 +358,7 @@ files:
|
|
354
358
|
- lib/generators/solidus_seo/install/templates/insert_product_list_helper.html.erb.deface
|
355
359
|
- lib/generators/solidus_seo/install/templates/paperclip_optimizer.rb
|
356
360
|
- lib/generators/solidus_seo/install/templates/remove_original_title_tag.deface
|
361
|
+
- lib/generators/solidus_seo/install/templates/replace_taxon_breadcrumbs_helper.html.erb.deface
|
357
362
|
- lib/solidus_seo.rb
|
358
363
|
- lib/solidus_seo/engine.rb
|
359
364
|
- lib/solidus_seo/factories.rb
|
@@ -373,6 +378,7 @@ files:
|
|
373
378
|
- lib/solidus_seo/model.rb
|
374
379
|
- lib/solidus_seo/version.rb
|
375
380
|
- spec/examples.txt
|
381
|
+
- spec/features/add_to_cart_spec.rb
|
376
382
|
- spec/features/checkout_complete_spec.rb
|
377
383
|
- spec/features/homepage_spec.rb
|
378
384
|
- spec/features/product_page_spec.rb
|
@@ -410,6 +416,7 @@ test_files:
|
|
410
416
|
- spec/features/checkout_complete_spec.rb
|
411
417
|
- spec/features/homepage_spec.rb
|
412
418
|
- spec/features/taxon_page_spec.rb
|
419
|
+
- spec/features/add_to_cart_spec.rb
|
413
420
|
- spec/features/product_page_spec.rb
|
414
421
|
- spec/support/testing_helpers.rb
|
415
422
|
- spec/system_helper.rb
|
@@ -1,39 +0,0 @@
|
|
1
|
-
module Spree
|
2
|
-
module BaseHelperDecorator
|
3
|
-
extend ActiveSupport::Concern
|
4
|
-
|
5
|
-
def self.prepended(base)
|
6
|
-
base.class_eval do
|
7
|
-
def breadcrumb_pairs(taxon)
|
8
|
-
crumbs = []
|
9
|
-
|
10
|
-
if taxon
|
11
|
-
crumbs << [Spree.t(:products), products_url]
|
12
|
-
crumbs += taxon.ancestors.collect { |a| [a.name, spree.nested_taxons_url(a.permalink)] } unless taxon.ancestors.empty?
|
13
|
-
crumbs << [taxon.name, spree.nested_taxons_url(taxon.permalink)]
|
14
|
-
else
|
15
|
-
crumbs << [Spree.t(:products), products_url]
|
16
|
-
end
|
17
|
-
|
18
|
-
crumbs
|
19
|
-
end
|
20
|
-
|
21
|
-
# TODO: Make this method replace original `taxon_breadcrumbs` so we can use super;
|
22
|
-
# prepending a module with anothe doesn't seem to be working as intended.
|
23
|
-
def taxon_breadcrumbs_jsonld(taxon, separator = ' » ', list_class = 'list-inline', list_item_class = 'list-inline-item')
|
24
|
-
return '' if current_page?('/') || taxon.nil?
|
25
|
-
|
26
|
-
separator = tag.span(separator.html_safe, class: 'breadcrumb-separator')
|
27
|
-
original_output = Nokogiri::HTML::DocumentFragment.parse(taxon_breadcrumbs(taxon, separator, list_class).to_s)
|
28
|
-
original_output.xpath('@itemscope|@itemtype|@itemprop|.//@itemscope|.//@itemtype|.//@itemprop').remove
|
29
|
-
original_output.search('.columns').first['class'] = ''
|
30
|
-
original_output.search('li').attr('class', list_item_class)
|
31
|
-
|
32
|
-
jsonld_breadcrumbs(breadcrumb_pairs(taxon)) + original_output.to_s.html_safe
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
::Spree::BaseHelper.prepend(self)
|
38
|
-
end
|
39
|
-
end
|