An open API service indexing awesome lists of open source software.

https://github.com/public-law/schema-dot-org

Easy structured data for websites. All validated for syntax and semantics. Simple declarative-style coding.
https://github.com/public-law/schema-dot-org

google-crawler json-ld rails ruby schema-org seo structured-data validations

Last synced: 3 months ago
JSON representation

Easy structured data for websites. All validated for syntax and semantics. Simple declarative-style coding.

Awesome Lists containing this project

README

          

## Table of Contents

- [SchemaDotOrg](#schemadotorg)
- [Usage](#usage)
- [Principle: No silent failures](#principle-no-silent-failures)
- [You are prevented from creating invalid markup](#you-are-prevented-from-creating-invalid-markup)
- [Supported Schema.org Types](#supported-schemaorg-types)
- [Examples](#examples)
- [BreadcrumbList](#breadcrumblist)
- [WebSite](#website)
- [Installation](#installation)
- [Development](#development)
- [Contributing](#contributing)
- [License](#license)

# SchemaDotOrg

Easily create [Structured Data](https://developers.google.com/search/docs/guides/intro-structured-data) with **correct syntax and semantics**.
Good structured data [helps enhance a website's search result appearance](https://developers.google.com/search/docs/guides/enhance-site):

> "Google Search works hard to understand the content of a page. You can help us by providing explicit clues about the meaning of a page…"

## Usage

Let's say you have a Rails app. First write plain-ruby code in a helper or controller.

Here's what that'd look like in a controller. Instantiate
the structured data object you want in your web page:

```ruby
@my_org = Organization.new(
name: 'Public.Law',
founder: Person.new(name: 'Robb Shecter'),
founding_date: Date.new(2009, 3, 6),
founding_location: Place.new(address: 'Portland, OR'),
email: 'support@public.law',
telephone: '+1 123 456 7890',
url: 'https://www.public.law',
logo: 'https://www.public.law/favicon-196x196.png',
same_as: [
'https://twitter.com/law_is_code',
'https://www.facebook.com/PublicDotLaw'
]
)
```

...and then output it in a template:

```html
<%= @my_org %>
```

...you'll get this perfectly formatted structured data in your HTML:

```html

{
"@context": "http://schema.org",
"@type": "Organization",
"name": "Public.Law",
"email": "support@public.law",
"telephone": "+1 123 456 7890",
"url": "https://www.public.law",
"logo": "https://www.public.law/favicon-196x196.png",
"foundingDate": "2009-03-06",
"founder": {
"@type": "Person",
"name": "Robb Shecter"
},
"foundingLocation": {
"@type": "Place",
"address": "Portland, OR"
},
"sameAs": [
"https://twitter.com/law_is_code",
"https://www.facebook.com/PublicDotLaw"
]
}

```

### Principle: No silent failures

We coded the library this way because the data is embedded in the HTML - and it's a
pain in the butt to manually check for errors. In my case, I manage 500,000 unique
pages in my Rails app. There's _no way_ I could place error-free structured data in
them without automatic validation.

`SchemaDotOrg` will validate your Ruby code, and if it's correct, will generate Schema.org JSON-LD markup when `#to_s`
is called. If you, e.g., didn't add the correct attributes, you'll get a descriptive error message pointing
you to the problem.

Notice how the `foundingDate` is in the required ISO-8601 format. In the same way, the `foundingLocation` is a `Place`
which adds the proper `@type` attribute. All Ruby snake-case names have been converted to the Schema.org standard camel-case.
Etc., etc.

### You are prevented from creating invalid markup

I make mistakes. So I wanted to know that if my page loads, the markup is good. I hate "silent failures".

If you use the wrong type or try to set an unknown attribute, SchemaDotOrg will
refuse to create the incorrect JSON-LD. Instead, you'll get a message explaining
the problem:

```ruby
Place.new(address: 12345)
# => ArgumentError: Address is class Integer, not String

Place.new(
address: '12345 Happy Street',
author: 'Hemmingway'
)
# => NoMethodError: undefined method `author'
```

In my experience, I never get errors from the lib. I code it once, it works, and then
I move on to other things.

> [!NOTE]
> This automatic validation comes from my [ValidatedObject gem](https://github.com/public-law/validated_object), which in turn,
> is a thin wrapper around ActiveRecord::Validations. So there's nothing magical going on here.

## Supported Schema.org Types

See each type's RSpec for an example of how to use it.

| Name | Schema.org Page | RSpec Spec | Source Code |
| ---------------------- | ------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
| AggregateOffer | [Schema.org](https://schema.org/AggregateOffer) | | [Source](https://github.com/public-law/schema-dot-org/blob/master/lib/schema_dot_org/aggregate_offer.rb) |
| BreadcrumbList | [Schema.org](https://schema.org/BreadcrumbList) | [RSpec](https://github.com/public-law/schema-dot-org/blob/master/spec/schema_dot_org/breadcrumb_list_spec.rb) | [Source](https://github.com/public-law/schema-dot-org/blob/master/lib/schema_dot_org/breadcrumb_list.rb) |
| CollegeOrUniversity | [Schema.org](https://schema.org/CollegeOrUniversity) | [RSpec](https://github.com/public-law/schema-dot-org/blob/master/spec/schema_dot_org/college_or_university_spec.rb) | [Source](https://github.com/public-law/schema-dot-org/blob/master/lib/schema_dot_org/college_or_university.rb) |
| Comment | [Schema.org](https://schema.org/Comment) | [RSpec](https://github.com/public-law/schema-dot-org/blob/master/spec/schema_dot_org/comment_spec.rb) | [Source](https://github.com/public-law/schema-dot-org/blob/master/lib/schema_dot_org/comment.rb) |
| ContactPoint | [Schema.org](https://schema.org/ContactPoint) | | [Source](https://github.com/public-law/schema-dot-org/blob/master/lib/schema_dot_org/contact_point.rb) |
| DiscussionForumPosting | [Schema.org](https://schema.org/DiscussionForumPosting) | [RSpec](https://github.com/public-law/schema-dot-org/blob/master/spec/schema_dot_org/discussion_forum_posting_spec.rb) | [Source](https://github.com/public-law/schema-dot-org/blob/master/lib/schema_dot_org/discussion_forum_posting.rb) |
| InteractionCounter | [Schema.org](https://schema.org/InteractionCounter) | [RSpec](https://github.com/public-law/schema-dot-org/blob/master/spec/schema_dot_org/interaction_counter_spec.rb) | [Source](https://github.com/public-law/schema-dot-org/blob/master/lib/schema_dot_org/interaction_counter.rb) |
| ItemList | [Schema.org](https://schema.org/ItemList) | [RSpec](https://github.com/public-law/schema-dot-org/blob/master/spec/schema_dot_org/item_list_spec.rb) | [Source](https://github.com/public-law/schema-dot-org/blob/master/lib/schema_dot_org/item_list.rb) |
| Language | [Schema.org](https://schema.org/Language) | [RSpec](https://github.com/public-law/schema-dot-org/blob/master/spec/schema_dot_org/language_spec.rb) | [Source](https://github.com/public-law/schema-dot-org/blob/master/lib/schema_dot_org/language.rb) |
| ListItem | [Schema.org](https://schema.org/ListItem) | | [Source](https://github.com/public-law/schema-dot-org/blob/master/lib/schema_dot_org/list_item.rb) |
| Offer | [Schema.org](https://schema.org/Offer) | | [Source](https://github.com/public-law/schema-dot-org/blob/master/lib/schema_dot_org/offer.rb) |
| Organization | [Schema.org](https://schema.org/Organization) | [RSpec](https://github.com/public-law/schema-dot-org/blob/master/spec/schema_dot_org/organization_spec.rb) | [Source](https://github.com/public-law/schema-dot-org/blob/master/lib/schema_dot_org/organization.rb) |
| Person | [Schema.org](https://schema.org/Person) | [RSpec](https://github.com/public-law/schema-dot-org/blob/master/spec/schema_dot_org/person_spec.rb) | [Source](https://github.com/public-law/schema-dot-org/blob/master/lib/schema_dot_org/person.rb) |
| Place | [Schema.org](https://schema.org/Place) | [RSpec](https://github.com/public-law/schema-dot-org/blob/master/spec/schema_dot_org/place_spec.rb) | [Source](https://github.com/public-law/schema-dot-org/blob/master/lib/schema_dot_org/place.rb) |
| PostalAddress | [Schema.org](https://schema.org/PostalAddress) | [RSpec](https://github.com/public-law/schema-dot-org/blob/master/spec/schema_dot_org/postal_address_spec.rb) | [Source](https://github.com/public-law/schema-dot-org/blob/master/lib/schema_dot_org/postal_address.rb) |
| Product | [Schema.org](https://schema.org/Product) | [RSpec](https://github.com/public-law/schema-dot-org/blob/master/spec/schema_dot_org/product_spec.rb) | [Source](https://github.com/public-law/schema-dot-org/blob/master/lib/schema_dot_org/product.rb) |
| SearchAction | [Schema.org](https://schema.org/SearchAction) | [RSpec](https://github.com/public-law/schema-dot-org/blob/master/spec/schema_dot_org/search_action_spec.rb) | [Source](https://github.com/public-law/schema-dot-org/blob/master/lib/schema_dot_org/search_action.rb) |
| WebSite | [Schema.org](https://schema.org/WebSite) | [RSpec](https://github.com/public-law/schema-dot-org/blob/master/spec/schema_dot_org/web_site_spec.rb) | [Source](https://github.com/public-law/schema-dot-org/blob/master/lib/schema_dot_org/web_site.rb) |

## Examples

### BreadcrumbList

The `make_breadcrumbs` convenience method creates a BreadcrumbList from a simple array of hashes:

```ruby
links = [
{ name: 'Home', url: 'https://example.com' },
{ name: 'Books', url: 'https://example.com/books' },
{ name: 'Science Fiction', url: 'https://example.com/books/sci-fi' },
{ name: 'Award Winners' } # Last item typically has no URL
]

SchemaDotOrg
.make_breadcrumbs(links)
.to_s
```

produces:

```html

{
"@context": "https://schema.org",
"@type": "BreadcrumbList",
"itemListElement": [
{
"@type": "ListItem",
"position": 1,
"name": "Home",
"item": "https://example.com"
},
{
"@type": "ListItem",
"position": 2,
"name": "Books",
"item": "https://example.com/books"
},
{
"@type": "ListItem",
"position": 3,
"name": "Science Fiction",
"item": "https://example.com/books/sci-fi"
},
{
"@type": "ListItem",
"position": 4,
"name": "Award Winners"
}
]
}

```

URLs are automatically validated - invalid URLs will raise an `ArgumentError` with a descriptive message.

### WebSite

Example with only the required attributes:

```ruby
WebSite.new(
name: 'Texas Public Law',
url: 'https://texas.public.law',
)
```

With the optional `SearchAction` to enable a [Sitelinks Searchbox](https://developers.google.com/search/docs/data-types/sitelinks-searchbox):

```ruby
WebSite.new(
name: 'Texas Public Law',
url: 'https://texas.public.law',
potential_action: SearchAction.new(
target: 'https://texas.public.law/?search={search_term_string}',
query_input: 'required name=search_term_string'
)
)
```

## Installation

Add this line to your application's Gemfile:

```ruby
gem 'schema_dot_org'
```

## Development

We aim to make it as easy as possible to contribute new Schema.Org types.
For example, here's a large one, [Organization]([url](https://github.com/public-law/schema-dot-org/blob/master/lib/schema_dot_org/organization.rb)).
The declarative-style coding keeps it readable:

```ruby
require 'date'

require_relative 'person'
require_relative 'place'
require_relative 'postal_address'

module SchemaDotOrg
##
# See https://schema.org/Organization
#
class Organization < SchemaType
validated_attr :address, type: PostalAddress, allow_nil: true
validated_attr :contact_points, type: union(ContactPoint, [ContactPoint]), allow_nil: true
validated_attr :email, type: String, allow_nil: true
validated_attr :founder, type: Person, allow_nil: true
validated_attr :founding_date, type: Date, allow_nil: true
validated_attr :founding_location, type: Place, allow_nil: true
validated_attr :legal_name, type: String, allow_nil: true
validated_attr :same_as, type: union(String, [String]), allow_nil: true
validated_attr :slogan, type: String, allow_nil: true
validated_attr :telephone, type: String, allow_nil: true

########################################
# Attributes that are required by Google
########################################
validated_attr :logo, type: String
validated_attr :name, type: String
validated_attr :url, type: String
end
end
```

The attributes are from the [Schema.org Organization spec](https://schema.org/Organization).

All Rails validations are available. These are just the attributes we've felt like
adding. PR's are welcome if you want to add more. Also for more Schema.org types.

## Contributing

Bug reports and pull requests are welcome on GitHub.

## License

The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).