solidus_seo 1.0.8 → 1.0.13
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/README.md +15 -15
- data/app/decorators/controllers/spree/checkout_controller_decorator.rb +23 -0
- data/app/decorators/controllers/spree/orders_controller_decorator.rb +15 -12
- data/app/decorators/models/spree/product_decorator.rb +2 -2
- data/app/views/solidus_seo/_facebook.html.erb +50 -6
- data/app/views/solidus_seo/_google-analytics.html.erb +13 -14
- data/app/views/solidus_seo/_google-tag-manager.html.erb +19 -20
- data/app/views/solidus_seo/_noscript_tags.html.erb +7 -0
- data/app/views/solidus_seo/_pinterest.html.erb +10 -13
- data/lib/generators/solidus_seo/install/install_generator.rb +2 -0
- data/lib/generators/solidus_seo/install/templates/insert_noscript_tags.html.erb.deface +4 -0
- data/lib/generators/solidus_seo/install/templates/replace_flash_messages_helper.html.erb.deface +5 -0
- data/lib/solidus_seo/jsonld/tag_helper.rb +1 -1
- data/lib/solidus_seo/version.rb +1 -1
- data/spec/examples.txt +40 -32
- data/spec/features/add_to_cart_spec.rb +15 -1
- data/spec/features/checkout_complete_spec.rb +5 -5
- data/spec/features/checkout_initiated_spec.rb +53 -0
- data/spec/features/homepage_spec.rb +16 -1
- data/spec/features/product_page_spec.rb +12 -1
- data/spec/features/taxon_page_spec.rb +1 -1
- metadata +12 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: affcb02125af16ffc2eb0aabe3850b0df3f8b0a8612c1627bd2953b043198d60
|
4
|
+
data.tar.gz: 2f80a9d259166a74e84bebb35f922c3a30ad0a50be98dc62187638484704dfb6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1dfc56ae1d28aad11304354619c97aae39a9f641a8332c5fc579da97db87c875efb0becf73a56227430103d60c4ab3896415638f69d5aa782d19d8558fa62b7d
|
7
|
+
data.tar.gz: b4e5ca4d432362aa6216b3a9c8f03ab0da34a6a521eabb18c312efb3bb91fc1e9e64d01dd2c3100ea3cc465c10799bdc5e73f662839f3b4cbb235d7a70bdd951
|
data/README.md
CHANGED
@@ -43,26 +43,26 @@ Here are the changes we make, via deface, in the default Solidus views as part o
|
|
43
43
|
- Replace the `<%== meta_data_tags %>` line for `<%= display_meta_tags %>`.
|
44
44
|
- Remove the `<title>` tag (`display_meta_tags` generates a new title tag).
|
45
45
|
|
46
|
-
|
47
46
|
- In `spree/layouts/spree_application.html.erb`
|
48
47
|
- Insert `<%= render 'solidus_seo/analytics' %>` just before `</head>`.
|
48
|
+
- Insert `<%= render 'solidus_seo/noscript_tags' %>` immediately after the `<body>` opening tag.
|
49
49
|
- Insert `<%= dump_jsonld %>` just before the `</body>` closing tag.
|
50
|
-
|
50
|
+
- Replace `<%= taxon_breadcrumbs(@taxon) %>` with (`<%= taxon_breadcrumbs_jsonld(@taxon) %>`) which does the same as the original plus prints a JSON-LD tag.
|
51
|
+
- Replace `<%= flash_messages %>` with (`<%= flash_messages(ignore_types: 'added_to_cart') %>`) which does the same as the original plus prints a JSON-LD tag.
|
51
52
|
|
52
53
|
- In `spree/products/show.html.erb`:
|
53
54
|
- Insert `<%= jsonld @product %>` anywhere inside the `cache` block.
|
54
55
|
|
55
|
-
|
56
56
|
- In `spree/shared/_products.html.erb`:
|
57
|
-
- Insert `<% jsonld_list(products) %>` at the bottom of the file. (Notice this helper doesn't generate any output, as instead it simply adds to the data that's later outputted by dump_jsonld)
|
57
|
+
- Insert `<% jsonld_list(products) %>` at the bottom of the file. (Notice this helper doesn't generate any output, as instead it simply adds to the data that's later outputted by `dump_jsonld`)
|
58
58
|
|
59
59
|
At this point, assuming you're using the default Solidus views and this extension's deface overrides, the features you've gained are:
|
60
60
|
|
61
61
|
- Default meta tags including open graph tags, describing a product on the PDP pages, and describing the store/site in all other pages.
|
62
|
-
- Store
|
63
|
-
- Product
|
64
|
-
- Breadcrumb
|
65
|
-
- ItemList
|
62
|
+
- Store JSON-LD markup on all your pages.
|
63
|
+
- Product JSON-LD markup in your PDP pages.
|
64
|
+
- Breadcrumb JSON-LD markup in your taxon pages.
|
65
|
+
- ItemList JSON-LD markup in your paginated product pages.
|
66
66
|
- Site-wide default paperclip image optimization (through image_optim)
|
67
67
|
- Page view and eCommerce conversion tracking (completed checkouts) enabled via presence of `GOOGLE_TAG_MANAGER_ID`, `GOOGLE_ANALYTICS_ID`, `FACEBOOK_PIXEL_ID`, `PINTEREST_TAG_ID` environment variables (only one Google integration should be enabled at a time).
|
68
68
|
|
@@ -70,7 +70,7 @@ At this point, assuming you're using the default Solidus views and this extensio
|
|
70
70
|
|
71
71
|
This gem is intended to provide a progressive implementation approach. To begin with, it defines some methods in your models to be used as an interface/source of your meta data. Moreover, it already provides some useful defaults that can be easily extended and customized, all inside your Spree models, via decorators.
|
72
72
|
|
73
|
-
Practically speaking, what this means is that simply by setting your store's metadata from the admin and calling the display_meta_tags helper in your layout, you'll get basic
|
73
|
+
Practically speaking, what this means is that simply by setting your store's metadata from the admin and calling the display_meta_tags helper in your layout, you'll get basic JSON-LD data included for your store. The output would be similar to the following:
|
74
74
|
|
75
75
|
```json
|
76
76
|
{
|
@@ -114,9 +114,9 @@ The basic requirements for the return values of your methods are straight-forwar
|
|
114
114
|
|
115
115
|
and
|
116
116
|
|
117
|
-
- `jsonld_data` must return a hash, holding a [
|
117
|
+
- `jsonld_data` must return a hash, holding a [JSON-LD definition](https://en.wikipedia.org/wiki/JSON-LD).
|
118
118
|
|
119
|
-
For the purpose of illustration, a simple example could be adding a new file to your Solidus app, `app/models/spree/order_decorator.rb`, to implement the jsonld_data interface for `Spree::Order`; the override for the seo_data interface would be placed and implemented similarly.
|
119
|
+
For the purpose of illustration, a simple example could be adding a new file to your Solidus app, `app/models/spree/order_decorator.rb`, to implement the `jsonld_data` interface for `Spree::Order`; the override for the seo_data interface would be placed and implemented similarly. NOTE: To be clear, this extension provides no default implementation for `Spree::Order.jsonld_data` - the code below is meant solely as an example override for those new to Solidus and who, accordingly, might be unfamiliar with its override mechanics (decorators).
|
120
120
|
|
121
121
|
```ruby
|
122
122
|
# app/models/spree/order_decorator.rb
|
@@ -152,19 +152,19 @@ Spree::Order.class_eval do
|
|
152
152
|
end
|
153
153
|
```
|
154
154
|
|
155
|
-
After adding the new decorator, all that's left would be adding a call to jsonld on the object
|
155
|
+
After adding the new decorator, all that's left would be adding a call to `jsonld` helper on the object, such as:
|
156
156
|
|
157
157
|
```erb
|
158
158
|
<%= jsonld(@order) %>
|
159
159
|
```
|
160
160
|
|
161
|
-
|
161
|
+
In short, `jsonld` parses any object that implements the `to_jsonld` method (added by `SolidusSeo::Model` module), which in turn makes use of the `jsonld_data` method, and returns a script tag.
|
162
162
|
|
163
|
-
Besides these base methods, there are some model-specific ones for Spree::Store and Spree::Product which are explained in the following sections. These are intended to provide you with some additional common and useful data.
|
163
|
+
Besides these base methods, there are some model-specific ones for `Spree::Store` and `Spree::Product` which are explained in the following sections. These are intended to provide you with some additional common and useful data.
|
164
164
|
|
165
165
|
#### Spree::Store
|
166
166
|
|
167
|
-
Again, even without any additional work beyond the initial installation, you get a solid/basic
|
167
|
+
Again, even without any additional work beyond the initial installation, you get a solid/basic JSON-LD definition for your `Spree::Store` model. By default:
|
168
168
|
|
169
169
|
```json
|
170
170
|
{
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Spree
|
4
|
+
module CheckoutControllerDecorator
|
5
|
+
def self.prepended(base)
|
6
|
+
base.class_eval do
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def before_address
|
11
|
+
flash[:checkout_initiated] =
|
12
|
+
@order.address? &&
|
13
|
+
request.referrer =~ /#{cart_path}\b/i &&
|
14
|
+
params[:action] == 'edit'
|
15
|
+
|
16
|
+
super
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
::Spree::StoreController.prepend(self)
|
22
|
+
end
|
23
|
+
end
|
@@ -24,23 +24,26 @@ module Spree
|
|
24
24
|
end.to_h.compact
|
25
25
|
|
26
26
|
cart_diff = cart_diff.map do |variant_sku, quantity|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
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
|
-
]
|
27
|
+
variant_hash = cart_diff_variant_payload(variant_sku)
|
28
|
+
variant_hash[:quantity] = quantity
|
29
|
+
|
30
|
+
[variant_sku, variant_hash]
|
39
31
|
end.to_h
|
40
32
|
|
41
33
|
flash[:added_to_cart] = cart_diff if cart_diff.present?
|
42
34
|
end
|
43
35
|
|
36
|
+
def cart_diff_variant_payload(sku)
|
37
|
+
variant = Spree::Variant.find_by(sku: sku)
|
38
|
+
|
39
|
+
{
|
40
|
+
id: variant.product.master.sku,
|
41
|
+
name: variant.product.name,
|
42
|
+
variant: variant.options_text,
|
43
|
+
price: variant.price
|
44
|
+
}
|
45
|
+
end
|
46
|
+
|
44
47
|
def order_contents_hash
|
45
48
|
return {} if current_order.blank?
|
46
49
|
|
@@ -17,10 +17,10 @@ module Spree
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def seo_images
|
20
|
-
return [] unless
|
20
|
+
return [] unless gallery.images.any? && gallery.images.first.attachment.file?
|
21
21
|
|
22
22
|
[
|
23
|
-
url_helper.image_url(
|
23
|
+
url_helper.image_url(gallery.images.first.attachment.url(:large), host: store_host),
|
24
24
|
].compact
|
25
25
|
end
|
26
26
|
|
@@ -1,16 +1,16 @@
|
|
1
1
|
<%
|
2
2
|
return if ENV['FACEBOOK_PIXEL_ID'].blank?
|
3
3
|
|
4
|
+
event_data = {}
|
5
|
+
|
4
6
|
if just_purchased
|
5
|
-
|
7
|
+
event_data[:order] = {
|
6
8
|
value: order.total,
|
7
9
|
currency: order.currency,
|
8
10
|
content_type: 'product',
|
9
11
|
contents: order.line_items.map do |line_item|
|
10
|
-
next unless line_item.variant
|
11
|
-
|
12
12
|
{ id: line_item.variant.sku, quantity: line_item.quantity }
|
13
|
-
end
|
13
|
+
end,
|
14
14
|
|
15
15
|
# custom properties
|
16
16
|
order_number: order.number,
|
@@ -20,6 +20,35 @@ if just_purchased
|
|
20
20
|
promo_total: order.promo_total
|
21
21
|
}
|
22
22
|
end
|
23
|
+
|
24
|
+
if flash[:added_to_cart].present?
|
25
|
+
event_data[:added_to_cart] = {
|
26
|
+
currency: order.currency,
|
27
|
+
content_type: 'product',
|
28
|
+
contents: flash[:added_to_cart].map do |variant_sku, variant|
|
29
|
+
{ id: variant_sku, quantity: variant['quantity'] }
|
30
|
+
end
|
31
|
+
}
|
32
|
+
end
|
33
|
+
|
34
|
+
if flash[:checkout_initiated].present?
|
35
|
+
event_data[:checkout] = {
|
36
|
+
value: order.total,
|
37
|
+
currency: order.currency,
|
38
|
+
contents: order.line_items.map do |line_item|
|
39
|
+
{ id: line_item.variant.sku, quantity: line_item.quantity }
|
40
|
+
end
|
41
|
+
}
|
42
|
+
end
|
43
|
+
|
44
|
+
if @product
|
45
|
+
event_data[:current_product] = {
|
46
|
+
content_type: 'product',
|
47
|
+
content_name: @product.name,
|
48
|
+
content_ids: [@product.master.sku]
|
49
|
+
}
|
50
|
+
end
|
51
|
+
|
23
52
|
%>
|
24
53
|
<script type="text/javascript" data-tag="facebook">
|
25
54
|
!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');
|
@@ -27,10 +56,25 @@ end
|
|
27
56
|
fbq('init', '<%= ENV['FACEBOOK_PIXEL_ID'] %>');
|
28
57
|
fbq('track', 'PageView');
|
29
58
|
|
30
|
-
<% if
|
31
|
-
fbq('track', 'Purchase', <%==
|
59
|
+
<% if event_data[:order].present? %>
|
60
|
+
fbq('track', 'Purchase', <%== event_data[:order].to_json %>);
|
32
61
|
window.solidusSeoDataLayer('facebook', 'purchase');
|
33
62
|
<% end %>
|
63
|
+
|
64
|
+
<% if event_data[:added_to_cart].present? %>
|
65
|
+
fbq('track', 'AddToCart', <%== event_data[:added_to_cart].to_json %>);
|
66
|
+
window.solidusSeoDataLayer('facebook', 'addtocart');
|
67
|
+
<% end %>
|
68
|
+
|
69
|
+
<% if event_data[:checkout].present? %>
|
70
|
+
fbq('track', 'InitiateCheckout', <%== event_data[:checkout].to_json %>);
|
71
|
+
window.solidusSeoDataLayer('facebook', 'initiatecheckout');
|
72
|
+
<% end %>
|
73
|
+
|
74
|
+
<% if event_data[:current_product].present? %>
|
75
|
+
fbq('track', 'ViewContent', <%== event_data[:current_product].to_json %>);
|
76
|
+
window.solidusSeoDataLayer('facebook', 'viewcontent');
|
77
|
+
<% end %>
|
34
78
|
</script>
|
35
79
|
<noscript>
|
36
80
|
<img height="1" width="1" src="https://www.facebook.com/tr?id=<%= ENV['FACEBOOK_PIXEL_ID'] %>&ev=PageView&noscript=1" />
|
@@ -6,8 +6,6 @@ if just_purchased
|
|
6
6
|
transaction_id: order.number,
|
7
7
|
value: order.total,
|
8
8
|
items: order.line_items.map do |line_item|
|
9
|
-
next unless line_item.variant
|
10
|
-
|
11
9
|
{
|
12
10
|
id: line_item.variant.sku,
|
13
11
|
name: line_item.variant.name,
|
@@ -15,7 +13,7 @@ if just_purchased
|
|
15
13
|
variant: line_item.variant.options_text,
|
16
14
|
quantity: line_item.quantity
|
17
15
|
}
|
18
|
-
end
|
16
|
+
end,
|
19
17
|
|
20
18
|
affiliation: current_store.name,
|
21
19
|
currency: order.currency,
|
@@ -25,16 +23,17 @@ if just_purchased
|
|
25
23
|
end
|
26
24
|
%>
|
27
25
|
<script async src="https://www.googletagmanager.com/gtag/js?id=<%= ENV['GOOGLE_ANALYTICS_ID'] %>"></script>
|
28
|
-
<script
|
29
|
-
|
30
|
-
|
31
|
-
|
26
|
+
<script>
|
27
|
+
window.dataLayer = window.dataLayer || [];
|
28
|
+
function gtag(){dataLayer.push(arguments);}
|
29
|
+
gtag('js', new Date());
|
32
30
|
|
33
|
-
|
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 %>
|
31
|
+
gtag('config', '<%= ENV['GOOGLE_ANALYTICS_ID'] %>');
|
40
32
|
</script>
|
33
|
+
|
34
|
+
<% if just_purchased %>
|
35
|
+
<script data-tag="google-analytics">
|
36
|
+
gtag('event', 'purchase', <%== order_data.to_json %>);
|
37
|
+
window.solidusSeoDataLayer('google-analytics', 'purchase');
|
38
|
+
</script>
|
39
|
+
<% end %>
|
@@ -14,8 +14,6 @@ if just_purchased
|
|
14
14
|
}
|
15
15
|
|
16
16
|
purchased_items = order.line_items.map do |line_item|
|
17
|
-
next unless line_item.variant
|
18
|
-
|
19
17
|
{
|
20
18
|
id: line_item.variant.sku,
|
21
19
|
name: line_item.variant.name,
|
@@ -23,28 +21,29 @@ if just_purchased
|
|
23
21
|
variant: line_item.variant.options_text,
|
24
22
|
quantity: line_item.quantity
|
25
23
|
}
|
26
|
-
end
|
24
|
+
end
|
27
25
|
end
|
28
26
|
%>
|
29
27
|
<script type="text/javascript" data-tag="google-tag-manager">
|
30
|
-
|
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
|
-
});
|
28
|
+
window.dataLayer = window.dataLayer || [];
|
41
29
|
|
42
|
-
|
43
|
-
|
30
|
+
<% if just_purchased %>
|
31
|
+
window.dataLayer.push({
|
32
|
+
'ecommerce': {
|
33
|
+
'purchase': {
|
34
|
+
'actionField': <%== order_data.to_json %>,
|
35
|
+
'products': <%== purchased_items.to_json %>
|
36
|
+
}
|
37
|
+
}
|
38
|
+
});
|
44
39
|
|
45
|
-
(
|
40
|
+
window.solidusSeoDataLayer('google-tag-manager', 'purchase');
|
41
|
+
<% end %>
|
42
|
+
</script>
|
43
|
+
<script>
|
44
|
+
(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
|
46
45
|
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
|
47
|
-
|
48
|
-
|
49
|
-
|
46
|
+
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
|
47
|
+
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
|
48
|
+
})(window,document,'script','dataLayer','<%= ENV['GOOGLE_TAG_MANAGER_ID'] %>');
|
50
49
|
</script>
|
@@ -0,0 +1,7 @@
|
|
1
|
+
<%
|
2
|
+
return if ENV['GOOGLE_TAG_MANAGER_ID'].blank?
|
3
|
+
%>
|
4
|
+
<!-- Google Tag Manager (noscript) -->
|
5
|
+
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=<%= ENV['GOOGLE_TAG_MANAGER_ID'] %>"
|
6
|
+
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
|
7
|
+
<!-- End Google Tag Manager (noscript) -->
|
@@ -1,18 +1,15 @@
|
|
1
1
|
<%
|
2
2
|
return if ENV['PINTEREST_TAG_ID'].blank?
|
3
3
|
|
4
|
-
|
5
|
-
add_to_cart_data = {}
|
6
|
-
order_data = {}
|
7
|
-
em_data = {}
|
4
|
+
event_data = {}
|
8
5
|
|
9
|
-
user_email =
|
6
|
+
user_email = try_spree_current_user&.email || current_order&.email
|
10
7
|
if user_email.present?
|
11
8
|
em_data = { em: user_email }
|
12
9
|
end
|
13
10
|
|
14
11
|
if just_purchased
|
15
|
-
|
12
|
+
event_data[:order] = {
|
16
13
|
value: order.total,
|
17
14
|
currency: order.currency,
|
18
15
|
order_quantity: order.line_items.sum(&:quantity),
|
@@ -32,7 +29,7 @@ if just_purchased
|
|
32
29
|
end
|
33
30
|
|
34
31
|
if @product
|
35
|
-
|
32
|
+
event_data[:product] = {
|
36
33
|
line_items: [
|
37
34
|
{
|
38
35
|
product_name: @product.name,
|
@@ -43,7 +40,7 @@ if @product
|
|
43
40
|
end
|
44
41
|
|
45
42
|
if flash[:added_to_cart].present?
|
46
|
-
|
43
|
+
event_data[:added_to_cart] = {
|
47
44
|
value: order.total,
|
48
45
|
currency: order.currency,
|
49
46
|
order_id: order.number,
|
@@ -66,16 +63,16 @@ end
|
|
66
63
|
pintrk('load', '<%= ENV['PINTEREST_TAG_ID'] %>' <%== em_data.present? ? ", #{em_data.to_json}" : '' %>);
|
67
64
|
pintrk('page');
|
68
65
|
|
69
|
-
pintrk('track', 'pagevisit'<%==
|
66
|
+
pintrk('track', 'pagevisit'<%== event_data[:product].present? ? ", #{event_data[:product].to_json}" : '' %>);
|
70
67
|
window.solidusSeoDataLayer('pinterest', 'pagevisit');
|
71
68
|
|
72
|
-
<% if
|
73
|
-
pintrk('track', 'addtocart', <%==
|
69
|
+
<% if event_data[:added_to_cart].present? %>
|
70
|
+
pintrk('track', 'addtocart', <%== event_data[:added_to_cart].to_json %>);
|
74
71
|
window.solidusSeoDataLayer('pinterest', 'addtocart');
|
75
72
|
<% end %>
|
76
73
|
|
77
|
-
<% if
|
78
|
-
pintrk('track', 'checkout', <%==
|
74
|
+
<% if event_data[:order].present? %>
|
75
|
+
pintrk('track', 'checkout', <%== event_data[:order].to_json %>);
|
79
76
|
window.solidusSeoDataLayer('pinterest', 'purchase');
|
80
77
|
<% end %>
|
81
78
|
</script>
|
@@ -35,6 +35,8 @@ module SolidusSeo
|
|
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
37
|
copy_file 'replace_taxon_breadcrumbs_helper.html.erb.deface', 'app/overrides/spree/layouts/spree_application/replace_taxon_breadcrumbs_helper.html.erb.deface'
|
38
|
+
copy_file 'insert_noscript_tags.html.erb.deface', 'app/overrides/spree/layouts/spree_application/insert_noscript_tags.html.erb.deface'
|
39
|
+
copy_file 'replace_flash_messages_helper.html.erb.deface', 'app/overrides/spree/layouts/spree_application/replace_flash_messages_helper.html.erb.deface'
|
38
40
|
end
|
39
41
|
end
|
40
42
|
end
|
data/lib/solidus_seo/version.rb
CHANGED
data/spec/examples.txt
CHANGED
@@ -1,32 +1,40 @@
|
|
1
|
-
example_id
|
2
|
-
|
3
|
-
./spec/features/add_to_cart_spec.rb[1:1:1]
|
4
|
-
./spec/features/
|
5
|
-
./spec/features/
|
6
|
-
./spec/features/checkout_complete_spec.rb[1:
|
7
|
-
./spec/features/checkout_complete_spec.rb[1:
|
8
|
-
./spec/features/
|
9
|
-
./spec/features/
|
10
|
-
./spec/features/
|
11
|
-
./spec/features/
|
12
|
-
./spec/features/
|
13
|
-
./spec/features/
|
14
|
-
./spec/features/
|
15
|
-
./spec/features/
|
16
|
-
./spec/features/
|
17
|
-
./spec/features/
|
18
|
-
./spec/features/
|
19
|
-
./spec/features/
|
20
|
-
./spec/features/
|
21
|
-
./spec/features/product_page_spec.rb[1:
|
22
|
-
./spec/features/product_page_spec.rb[1:
|
23
|
-
./spec/features/product_page_spec.rb[1:
|
24
|
-
./spec/features/
|
25
|
-
./spec/features/
|
26
|
-
./spec/features/
|
27
|
-
./spec/features/
|
28
|
-
./spec/features/
|
29
|
-
./spec/features/
|
30
|
-
./spec/features/
|
31
|
-
./spec/features/
|
32
|
-
./spec/features/taxon_page_spec.rb[1:
|
1
|
+
example_id | status | run_time |
|
2
|
+
------------------------------------------------- | ------- | --------------- |
|
3
|
+
./spec/features/add_to_cart_spec.rb[1:1:1] | passed | 0.59063 seconds |
|
4
|
+
./spec/features/add_to_cart_spec.rb[1:2:1] | passed | 0.92144 seconds |
|
5
|
+
./spec/features/add_to_cart_spec.rb[1:2:2] | passed | 0.87052 seconds |
|
6
|
+
./spec/features/checkout_complete_spec.rb[1:1:1] | passed | 0.55618 seconds |
|
7
|
+
./spec/features/checkout_complete_spec.rb[1:2:1] | passed | 4.19 seconds |
|
8
|
+
./spec/features/checkout_complete_spec.rb[1:3:1] | passed | 0.91829 seconds |
|
9
|
+
./spec/features/checkout_complete_spec.rb[1:4:1] | passed | 1.2 seconds |
|
10
|
+
./spec/features/checkout_initiated_spec.rb[1:1:1] | pending | 0.13867 seconds |
|
11
|
+
./spec/features/checkout_initiated_spec.rb[1:2:1] | pending | 0.1143 seconds |
|
12
|
+
./spec/features/checkout_initiated_spec.rb[1:3:1] | passed | 0.71343 seconds |
|
13
|
+
./spec/features/checkout_initiated_spec.rb[1:4:1] | pending | 0.10753 seconds |
|
14
|
+
./spec/features/homepage_spec.rb[1:1:1] | passed | 0.29998 seconds |
|
15
|
+
./spec/features/homepage_spec.rb[1:1:2] | passed | 0.34618 seconds |
|
16
|
+
./spec/features/homepage_spec.rb[1:2:1] | passed | 0.28189 seconds |
|
17
|
+
./spec/features/homepage_spec.rb[1:2:2] | passed | 0.30156 seconds |
|
18
|
+
./spec/features/homepage_spec.rb[1:3:1] | passed | 0.27539 seconds |
|
19
|
+
./spec/features/homepage_spec.rb[1:3:2] | passed | 0.29419 seconds |
|
20
|
+
./spec/features/homepage_spec.rb[1:4:1:1] | passed | 0.37499 seconds |
|
21
|
+
./spec/features/product_page_spec.rb[1:1:1] | passed | 0.43008 seconds |
|
22
|
+
./spec/features/product_page_spec.rb[1:1:2] | passed | 0.3833 seconds |
|
23
|
+
./spec/features/product_page_spec.rb[1:1:3] | passed | 0.38015 seconds |
|
24
|
+
./spec/features/product_page_spec.rb[1:2:1] | passed | 0.40948 seconds |
|
25
|
+
./spec/features/product_page_spec.rb[1:2:2:1] | passed | 0.38353 seconds |
|
26
|
+
./spec/features/product_page_spec.rb[1:2:3:1] | passed | 0.38026 seconds |
|
27
|
+
./spec/features/product_page_spec.rb[1:3:1] | passed | 0.3795 seconds |
|
28
|
+
./spec/features/product_page_spec.rb[1:3:2] | passed | 0.43348 seconds |
|
29
|
+
./spec/features/product_page_spec.rb[1:3:3] | passed | 0.36624 seconds |
|
30
|
+
./spec/features/product_page_spec.rb[1:4:1:1] | passed | 0.41513 seconds |
|
31
|
+
./spec/features/product_page_spec.rb[1:4:2:1] | passed | 0.50718 seconds |
|
32
|
+
./spec/features/taxon_page_spec.rb[1:1:1] | passed | 0.41762 seconds |
|
33
|
+
./spec/features/taxon_page_spec.rb[1:1:2] | passed | 0.41961 seconds |
|
34
|
+
./spec/features/taxon_page_spec.rb[1:1:3] | passed | 0.42318 seconds |
|
35
|
+
./spec/features/taxon_page_spec.rb[1:2:1] | passed | 0.434 seconds |
|
36
|
+
./spec/features/taxon_page_spec.rb[1:2:2:1] | passed | 0.42845 seconds |
|
37
|
+
./spec/features/taxon_page_spec.rb[1:2:3:1] | passed | 0.3977 seconds |
|
38
|
+
./spec/features/taxon_page_spec.rb[1:3:1] | passed | 0.41176 seconds |
|
39
|
+
./spec/features/taxon_page_spec.rb[1:3:2] | passed | 0.41971 seconds |
|
40
|
+
./spec/features/taxon_page_spec.rb[1:4:1] | passed | 0.67247 seconds |
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
describe 'Add to cart', type: :system do
|
4
|
-
let!(:store) {
|
4
|
+
let!(:store) { create(:store) }
|
5
5
|
let!(:order) { create :completed_order_with_totals }
|
6
6
|
let!(:line_item) { order.line_items.first }
|
7
7
|
|
@@ -15,6 +15,16 @@ describe 'Add to cart', type: :system do
|
|
15
15
|
find('#add-to-cart-button').click
|
16
16
|
end
|
17
17
|
|
18
|
+
context 'when FACEBOOK_PIXEL_ID environment variable is present' do
|
19
|
+
let(:env_variable) { 'FACEBOOK_PIXEL_ID' }
|
20
|
+
|
21
|
+
it 'tracks "add to cart" event with product data' do
|
22
|
+
expect(page).to track_analytics_event :facebook, 'addtocart', [
|
23
|
+
'fbq', 'track', 'AddToCart', line_item.sku
|
24
|
+
]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
18
28
|
context 'when PINTEREST_TAG_ID environment variable is present' do
|
19
29
|
let(:env_variable) { 'PINTEREST_TAG_ID' }
|
20
30
|
|
@@ -24,6 +34,10 @@ describe 'Add to cart', type: :system do
|
|
24
34
|
line_item.name, line_item.variant.sku, line_item.variant.price
|
25
35
|
]
|
26
36
|
end
|
37
|
+
|
38
|
+
it 'skips printing a flash message to the user with added_to_cart raw data' do
|
39
|
+
expect(page).to_not have_css '.flash.added_to_cart'
|
40
|
+
end
|
27
41
|
end
|
28
42
|
end
|
29
43
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
describe 'Checkout complete', type: :system do
|
4
|
-
let!(:store) {
|
4
|
+
let!(:store) { create(:store) }
|
5
5
|
let!(:taxon) { create :taxon, name: 'MyTaxon' }
|
6
6
|
let!(:order) { create :completed_order_with_totals }
|
7
7
|
let!(:line_item) { order.line_items.first }
|
@@ -19,7 +19,7 @@ describe 'Checkout complete', type: :system do
|
|
19
19
|
context 'when GOOGLE_TAG_MANAGER_ID environment variable is present' do
|
20
20
|
let(:env_variable) { 'GOOGLE_TAG_MANAGER_ID' }
|
21
21
|
|
22
|
-
it '
|
22
|
+
it 'tracks "purchase" event with product data' do
|
23
23
|
subject
|
24
24
|
expect(page).to track_analytics_event 'google-tag-manager', 'purchase', ['ecommerce', 'purchase', order.number, order.total, line_item.sku]
|
25
25
|
end
|
@@ -28,7 +28,7 @@ describe 'Checkout complete', type: :system do
|
|
28
28
|
context 'when GOOGLE_ANALYTICS_ID environment variable is present' do
|
29
29
|
let(:env_variable) { 'GOOGLE_ANALYTICS_ID' }
|
30
30
|
|
31
|
-
it '
|
31
|
+
it 'tracks "purchase" event with product data' do
|
32
32
|
subject
|
33
33
|
expect(page).to track_analytics_event 'google-analytics', 'purchase', [
|
34
34
|
'event', 'purchase', 'transaction_id', order.number,
|
@@ -41,7 +41,7 @@ describe 'Checkout complete', type: :system do
|
|
41
41
|
context 'when FACEBOOK_PIXEL_ID environment variable is present' do
|
42
42
|
let(:env_variable) { 'FACEBOOK_PIXEL_ID' }
|
43
43
|
|
44
|
-
it '
|
44
|
+
it 'tracks "Purchase" event with product data' do
|
45
45
|
subject
|
46
46
|
expect(page).to track_analytics_event :facebook, 'purchase', ['track', 'Purchase', order.total, line_item.sku, line_item.quantity, order.number]
|
47
47
|
end
|
@@ -50,7 +50,7 @@ describe 'Checkout complete', type: :system do
|
|
50
50
|
context 'when PINTEREST_TAG_ID environment variable is present' do
|
51
51
|
let(:env_variable) { 'PINTEREST_TAG_ID' }
|
52
52
|
|
53
|
-
it '
|
53
|
+
it 'tracks "checkout" event with product data' do
|
54
54
|
subject
|
55
55
|
expect(page).to track_analytics_event :pinterest, 'purchase', ['track', 'checkout', order.total, line_item.sku, line_item.name, line_item.price]
|
56
56
|
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
describe 'Checkout initated', type: :system do
|
4
|
+
let!(:store) { create(:store) }
|
5
|
+
let!(:taxon) { create :taxon, name: 'MyTaxon' }
|
6
|
+
let!(:product) { create(:base_product, taxons: [taxon]) }
|
7
|
+
let(:order) { Spree::Order.last }
|
8
|
+
|
9
|
+
stub_authorization!
|
10
|
+
|
11
|
+
before do
|
12
|
+
stub_const 'ENV', ENV.to_h.merge(env_variable => 'XXX-YYYYY')
|
13
|
+
end
|
14
|
+
|
15
|
+
subject do
|
16
|
+
visit spree.product_path(product)
|
17
|
+
find('#add-to-cart-button').click
|
18
|
+
find('#checkout-link').click
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'when GOOGLE_TAG_MANAGER_ID environment variable is present' do
|
22
|
+
let(:env_variable) { 'GOOGLE_TAG_MANAGER_ID' }
|
23
|
+
|
24
|
+
it 'tracks "InitiateCheckout" event with product data' do
|
25
|
+
skip
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'when GOOGLE_ANALYTICS_ID environment variable is present' do
|
30
|
+
let(:env_variable) { 'GOOGLE_ANALYTICS_ID' }
|
31
|
+
|
32
|
+
it 'tracks "InitiateCheckout" event with product data' do
|
33
|
+
skip
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context 'when FACEBOOK_PIXEL_ID environment variable is present' do
|
38
|
+
let(:env_variable) { 'FACEBOOK_PIXEL_ID' }
|
39
|
+
|
40
|
+
it 'tracks "InitiateCheckout" event with product data' do
|
41
|
+
subject
|
42
|
+
expect(page).to track_analytics_event :facebook, 'initiatecheckout', ['track', 'InitiateCheckout', order.total, order.currency, order.line_items.first.sku]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
context 'when PINTEREST_TAG_ID environment variable is present' do
|
47
|
+
let(:env_variable) { 'PINTEREST_TAG_ID' }
|
48
|
+
|
49
|
+
it 'tracks "checkout" event with product data' do
|
50
|
+
skip
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
describe "Homepage", type: :system do
|
2
|
-
let!(:store) {
|
2
|
+
let!(:store) { create(:store) }
|
3
3
|
let(:seo_name) { 'My store SEO name' }
|
4
4
|
let(:seo_image) { 'https://example.com/path/store.jpg' }
|
5
5
|
let(:seo_description) { 'My store SEO description' }
|
@@ -59,4 +59,19 @@ describe "Homepage", type: :system do
|
|
59
59
|
expect(page).to have_css "meta[property='og:description'][content='#{seo_description}']", visible: false
|
60
60
|
end
|
61
61
|
end
|
62
|
+
|
63
|
+
context 'noscript tags' do
|
64
|
+
context 'when GOOGLE_TAG_MANAGER_ID is present' do
|
65
|
+
let(:env_variable) { 'GOOGLE_TAG_MANAGER_ID' }
|
66
|
+
|
67
|
+
before do
|
68
|
+
stub_const 'ENV', ENV.to_h.merge(env_variable => 'XXX-YYYYY')
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'contains noscript tag for GTM' do
|
72
|
+
subject
|
73
|
+
expect(page).to have_text :all, "https://www.googletagmanager.com/ns.html"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
62
77
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
describe "Product page", type: :system do
|
2
|
-
let!(:store) {
|
2
|
+
let!(:store) { create(:store) }
|
3
3
|
let(:store_seo_name) { 'My store SEO name' }
|
4
4
|
|
5
5
|
let!(:taxon) { create(:taxon, name: 'MyTaxon') }
|
@@ -97,6 +97,17 @@ describe "Product page", type: :system do
|
|
97
97
|
stub_const 'ENV', ENV.to_h.merge(env_variable => 'XXX-YYYYY')
|
98
98
|
end
|
99
99
|
|
100
|
+
context 'when FACEBOOK_PIXEL_ID environment variable is present' do
|
101
|
+
let(:env_variable) { 'FACEBOOK_PIXEL_ID' }
|
102
|
+
|
103
|
+
it 'tracks "ViewContent" event with product data' do
|
104
|
+
subject
|
105
|
+
expect(page).to track_analytics_event :facebook, 'viewcontent', [
|
106
|
+
'fbq', 'track', 'ViewContent', product.name, product.master.sku
|
107
|
+
]
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
100
111
|
context 'when PINTEREST_TAG_ID environment variable is present' do
|
101
112
|
let(:env_variable) { 'PINTEREST_TAG_ID' }
|
102
113
|
|
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.13
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Karma Creative
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-07-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: solidus_core
|
@@ -337,6 +337,7 @@ 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/checkout_controller_decorator.rb
|
340
341
|
- app/decorators/controllers/spree/orders_controller_decorator.rb
|
341
342
|
- app/decorators/controllers/spree/store_controller_decorator.rb
|
342
343
|
- app/decorators/helpers/spree/core/controller_helpers/common_decorator.rb
|
@@ -346,6 +347,7 @@ files:
|
|
346
347
|
- app/views/solidus_seo/_facebook.html.erb
|
347
348
|
- app/views/solidus_seo/_google-analytics.html.erb
|
348
349
|
- app/views/solidus_seo/_google-tag-manager.html.erb
|
350
|
+
- app/views/solidus_seo/_noscript_tags.html.erb
|
349
351
|
- app/views/solidus_seo/_pinterest.html.erb
|
350
352
|
- config/locales/en.yml
|
351
353
|
- config/routes.rb
|
@@ -354,10 +356,12 @@ files:
|
|
354
356
|
- lib/generators/solidus_seo/install/templates/insert_analytics_in_layout.html.erb.deface
|
355
357
|
- lib/generators/solidus_seo/install/templates/insert_display_meta_tags_helper.html.erb.deface
|
356
358
|
- lib/generators/solidus_seo/install/templates/insert_dump_jsonld_helper.html.erb.deface
|
359
|
+
- lib/generators/solidus_seo/install/templates/insert_noscript_tags.html.erb.deface
|
357
360
|
- lib/generators/solidus_seo/install/templates/insert_product_jsonld_helper.html.erb.deface
|
358
361
|
- lib/generators/solidus_seo/install/templates/insert_product_list_helper.html.erb.deface
|
359
362
|
- lib/generators/solidus_seo/install/templates/paperclip_optimizer.rb
|
360
363
|
- lib/generators/solidus_seo/install/templates/remove_original_title_tag.deface
|
364
|
+
- lib/generators/solidus_seo/install/templates/replace_flash_messages_helper.html.erb.deface
|
361
365
|
- lib/generators/solidus_seo/install/templates/replace_taxon_breadcrumbs_helper.html.erb.deface
|
362
366
|
- lib/solidus_seo.rb
|
363
367
|
- lib/solidus_seo/engine.rb
|
@@ -380,6 +384,7 @@ files:
|
|
380
384
|
- spec/examples.txt
|
381
385
|
- spec/features/add_to_cart_spec.rb
|
382
386
|
- spec/features/checkout_complete_spec.rb
|
387
|
+
- spec/features/checkout_initiated_spec.rb
|
383
388
|
- spec/features/homepage_spec.rb
|
384
389
|
- spec/features/product_page_spec.rb
|
385
390
|
- spec/features/taxon_page_spec.rb
|
@@ -390,7 +395,7 @@ homepage: https://github.com/karmakatahdin/solidus_seo
|
|
390
395
|
licenses:
|
391
396
|
- BSD-3-Clause
|
392
397
|
metadata: {}
|
393
|
-
post_install_message:
|
398
|
+
post_install_message:
|
394
399
|
rdoc_options: []
|
395
400
|
require_paths:
|
396
401
|
- lib
|
@@ -405,15 +410,16 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
405
410
|
- !ruby/object:Gem::Version
|
406
411
|
version: '0'
|
407
412
|
requirements: []
|
408
|
-
rubyforge_project:
|
413
|
+
rubyforge_project:
|
409
414
|
rubygems_version: 2.7.6.2
|
410
|
-
signing_key:
|
415
|
+
signing_key:
|
411
416
|
specification_version: 4
|
412
417
|
summary: Enhanced SEO in Solidus
|
413
418
|
test_files:
|
414
419
|
- spec/spec_helper.rb
|
415
420
|
- spec/examples.txt
|
416
421
|
- spec/features/checkout_complete_spec.rb
|
422
|
+
- spec/features/checkout_initiated_spec.rb
|
417
423
|
- spec/features/homepage_spec.rb
|
418
424
|
- spec/features/taxon_page_spec.rb
|
419
425
|
- spec/features/add_to_cart_spec.rb
|