Research
Security News
Malicious npm Package Targets Solana Developers and Hijacks Funds
A malicious npm package targets Solana developers, rerouting funds in 2% of transactions to a hardcoded address.
Successful stores keep SEO as a top priority. This Solidus extension adds common-sense defaults for structured data, meta tags, Open Graph protocol, and image optimization.
Please note that we are still striving to improve this extension and we warmly welcome community contribution, engagement, and support.
Let us know what you'd like to see added next; we promise to respond to any issues as soon as possible.
Add solidus_seo
to your Gemfile:
gem 'solidus_seo'
Bundle your dependencies and run the installation generator):
NOTE: During this step, you will be prompted to decide whether or not you'd like to generate the overrides that are included in solidus_seo. These overrides require 'deface' and are intended to be used with solidus_frontend. If you are not using solidus_frontend, you'll have to figure out where is best to manually insert the solidus_seo helpers into your custom views. Continue reading for more information.
bundle
bundle exec rails g solidus_seo:install
Make sure you've added your store metadata from the Solidus store administration page, like SEO title, store URL and meta description.
(Optional) Override the stubbed methods and/or default helpers provided by this gem to provide extended functionality. [This is further explained below in the Usage section.]
As mentioned in the above section, we use Deface to insert some helpers that generate the meta and structured data. This, of course, only works if you're using/overriding the default Solidus views from solidus_frontend.
Otherwise, if you're using custom non-Solidus views, we assume you're smart enough to figure out for yourself where to put these helpers ;)
Here are the changes we make, via deface, in the default Solidus views as part of the minimal installation:
In spree/shared/_head.html.erb
:
<%== meta_data_tags %>
line for <%= display_meta_tags %>
.<title>
tag (display_meta_tags
generates a new title tag).In spree/layouts/spree_application.html.erb
<%= render 'solidus_seo/analytics' %>
just before </head>
.<%= render 'solidus_seo/noscript_tags' %>
immediately after the <body>
opening tag.<%= dump_jsonld %>
just before the </body>
closing tag.<%= taxon_breadcrumbs(@taxon) %>
with (<%= taxon_breadcrumbs_jsonld(@taxon) %>
) which does the same as the original plus prints a JSON-LD tag.<%= flash_messages %>
with (<%= flash_messages(ignore_types: 'added_to_cart') %>
) which does the same as the original plus prints a JSON-LD tag.In spree/products/show.html.erb
:
<%= jsonld @product %>
anywhere inside the cache
block.In spree/shared/_products.html.erb
:
<% 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
)At this point, assuming you're using the default Solidus views and this extension's deface overrides, the features you've gained are:
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).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.
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:
{
"@context": "http://schema.org",
"@type": "Store",
"name": "Your Store Name",
"logo": "https://yourstore.com/store_logo.jpg",
"image": "https://yourstore.com/store_logo.jpg",
"url": "https://yourstore.com",
"@id": "https://yourstore.com",
}
Likewise, with no additional customization, overrides, or decorators, a call to jsonld @product
will produce the following example output:
{
"@context": "http://schema.org/",
"@type": "Product",
"name": "Ruby on Rails Tote",
"url": "http://example.com/products/ruby-on-rails-tote",
"image": [
"http://example.com/spree/products/21/large/ror_tote.jpeg?1538529540"
],
"description": "Ruby on Rails Tote",
"sku": "ROR-00011",
"offers": {
"@type": "Offer",
"priceCurrency": "USD",
"price": "15.99",
"itemCondition": "http://schema.org/NewCondition",
"availability": "http://schema.org/InStock"
}
}
Beyond this initial behavior, you can override any of these base methods with your own data source. We recommend you take a look at the source to know which properties are available for easy overriding.
The basic requirements for the return values of your methods are straight-forward:
seo_data
must return a hash with the same structure expected by set_meta_tags
and
jsonld_data
must return a hash, holding a JSON-LD definition.
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).
# app/models/spree/order_decorator.rb
Spree::Order.class_eval do
include SolidusSeo::Model
def jsonld_data
{
"@context": "http://schema.org/",
"@type": "Order",
"seller": Spree::Store.default.jsonld_data,
"customer": {
"@type": "Person",
"name": billing_address.full_name,
...
},
"orderedItem": [
{
"@type": "OrderItem",
"orderItemNumber": line_items.first.sku,
"orderQuantity": line_items.first.quantity,
"orderedItem": line_items.first.product.jsonld_data,
"orderItemStatus": "http://schema.org/OrderDelivered",
"orderDelivery": {
"@type": "ParcelDelivery",
"expectedArrivalFrom": ...
}
}
]
}
end
end
After adding the new decorator, all that's left would be adding a call to jsonld
helper on the object, such as:
<%= jsonld(@order) %>
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.
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.
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:
{
"@context": "http://schema.org",
"@type": "Store",
"name": "Your Store Name",
"logo": "https://yourstore.com/store_logo.jpg",
"image": "https://yourstore.com/store_logo.jpg",
"url": "https://yourstore.com",
"@id": "https://yourstore.com",
}
Beyond this, there are properties you'll probably want to add to your store definition, like address and profile.
We provide some data-source methods for these common properties without having to redefine the jsonld_data
method. You can therefore easily override any of them from within your Solidus app (inside app/models/spree/store_decorator.rb
). For example:
# app/models/spree/store_decorator.rb
Spree::Store.class_eval do
def address_prop
{
"streetAddress": "123 Custom Address St",
"addressLocality": "Cityville",
"addressRegion": "New Vermont",
"postalCode": "05001",
"addressCountry": "US"
}
end
end
The *_prop
stubbed methods are listed below:
def address_prop
{
"streetAddress": "1600 Pennsylvania Avenue",
"addressLocality": "Washington",
"addressRegion": "District of Columbia",
"postalCode": "20500",
"addressCountry": "US"
}
end
def contact_points_prop
[
{
"telephone": "+11111111111",
"contactType": "customer service",
},
# ...
]
end
def opening_hours_specification_prop
[
{
"dayOfWeek": [
"Monday",
"Wednesday",
"Friday"
],
"opens": "12:00",
"closes": "22:00"
},
# ...
]
end
def geo_prop
{
"latitude": -37.3,
"longitude": -12.68
}
end
def same_as_prop
[
'https://facebook.com/mystore',
'https://twitter.com/mystore',
# ...
]
end
Using the sample data above, the final output would look like this :
{
"@context": "http://schema.org",
"@type": "Store",
"name": "Your Store Name",
"logo": "https://yourstore.com/store_logo.jpg",
"image": "https://yourstore.com/store_logo.jpg",
"url": "https://yourstore.com",
"@id": "https://yourstore.com",
"contactPoint": [
{
"@type": "ContactPoint",
"contactType": "customer service",
"telephone": "+11111111111"
}
],
"address": {
"@type": "PostalAddress",
"streetAddress": "1600 Pennsylvania Avenue",
"addressLocality": "Washington",
"addressRegion": "District of Columbia",
"postalCode": "20500",
"addressCountry": "US"
},
"geo": {
"@type": "GeoCoordinates",
"latitude": -37.3,
"longitude": -12.68
},
"sameAs": [
"https://facebook.com/mystore",
"https://twitter.com/mystore"
],
"openingHoursSpecification": [
{
"@type": "OpeningHoursSpecification",
"dayOfWeek": [
"Monday",
"Wednesday",
"Friday"
],
"opens": "12:00",
"closes": "22:00"
}
]
}
Finally, there are other methods that centralize common data used in multiple places in both the seo_data
and jsonld_data
default definitions: seo_image
, seo_description
and seo_tagline
. (seo_tagline
is a general phrase that will be shown as part of the page title on the homepage.) Again, these provide sensible default behavior and can be overridden if required.
And if you're wondering where the seo_keywords
helper is, well, it doesn't exist - and honestly, you should no longer care about your meta keywords at all.
Beside the seo_data
and jsonld_data
methods, there are also some common convenience methods for this particular model, namely:
seo_name
seo_url
seo_images
: An array of -at least- one absolute image url. The recommendation is to use 3 images, each with one of the following proportions: 1x1, 19:6, 4:3.seo_description
: By default, it fallbacks to the meta_description
field or if empty, to description
.seo_brand
: By default, it uses the name of any assigned taxon that belongs to a taxonomy named 'Brand' or 'Brands'.seo_currency
seo_price
(NOTE: Unlike Spree::Store
model, there are no *_prop
methods for Spree::Product
.)
In order to enable image optimization, just tell paperclip to use :paperclip_optimizer
processor as described in Paperclip Optimizer's usage guide. We already provide a paperclip optimizer initializer and configuration file (created at config/image_optim.yml
) with sensible defaults for a quick start and to save you some hassle. We recommend that you also optimize your pipeline assets by using config.assets.image_optim = true
in production.rb
(not recommended for development and test).
First bundle your dependencies, then run rake
. rake
will default to building the dummy app if it does not exist, then it will run specs, and Rubocop static code analysis. The dummy app can be regenerated by using rake test_app
.
bundle
bundle exec rake
When testing your application's integration with this extension you may use its factories. Simply add this require statement to your spec_helper:
require 'solidus_seo/factories'
Copyright (c) 2018 Karma Creative LLC, released under the New BSD License
FAQs
Unknown package
We found that solidus_seo demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
A malicious npm package targets Solana developers, rerouting funds in 2% of transactions to a hardcoded address.
Security News
Research
Socket researchers have discovered malicious npm packages targeting crypto developers, stealing credentials and wallet data using spyware delivered through typosquats of popular cryptographic libraries.
Security News
Socket's package search now displays weekly downloads for npm packages, helping developers quickly assess popularity and make more informed decisions.