{"id":28789894,"url":"https://github.com/public-law/schema-dot-org","last_synced_at":"2025-11-11T18:27:02.953Z","repository":{"id":48843353,"uuid":"121331615","full_name":"public-law/schema-dot-org","owner":"public-law","description":"Easy structured data for websites. All validated for syntax and semantics. Simple declarative-style coding.","archived":false,"fork":false,"pushed_at":"2025-06-09T02:43:48.000Z","size":296,"stargazers_count":65,"open_issues_count":3,"forks_count":33,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-06-17T10:59:38.897Z","etag":null,"topics":["google-crawler","json-ld","rails","ruby","schema-org","seo","structured-data","validations"],"latest_commit_sha":null,"homepage":"https://rubygems.org/gems/schema_dot_org","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/public-law.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2018-02-13T02:57:23.000Z","updated_at":"2025-06-10T17:39:58.000Z","dependencies_parsed_at":"2025-06-08T18:05:52.863Z","dependency_job_id":"abf122de-3f08-4078-8aec-8720e8ba4723","html_url":"https://github.com/public-law/schema-dot-org","commit_stats":null,"previous_names":["public-law/schema-dot-org"],"tags_count":29,"template":false,"template_full_name":null,"purl":"pkg:github/public-law/schema-dot-org","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/public-law%2Fschema-dot-org","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/public-law%2Fschema-dot-org/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/public-law%2Fschema-dot-org/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/public-law%2Fschema-dot-org/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/public-law","download_url":"https://codeload.github.com/public-law/schema-dot-org/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/public-law%2Fschema-dot-org/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":260346742,"owners_count":22995135,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["google-crawler","json-ld","rails","ruby","schema-org","seo","structured-data","validations"],"created_at":"2025-06-17T22:30:39.914Z","updated_at":"2025-11-11T18:27:02.941Z","avatar_url":"https://github.com/public-law.png","language":"Ruby","funding_links":[],"categories":["Ruby"],"sub_categories":[],"readme":"## Table of Contents\n\n- [SchemaDotOrg](#schemadotorg)\n  - [Usage](#usage)\n    - [Principle: No silent failures](#principle-no-silent-failures)\n    - [You are prevented from creating invalid markup](#you-are-prevented-from-creating-invalid-markup)\n  - [Supported Schema.org Types](#supported-schemaorg-types)\n  - [Examples](#examples)\n    - [BreadcrumbList](#breadcrumblist)\n    - [WebSite](#website)\n  - [Installation](#installation)\n  - [Development](#development)\n  - [Contributing](#contributing)\n  - [License](#license)\n\n# SchemaDotOrg\n\nEasily create [Structured Data](https://developers.google.com/search/docs/guides/intro-structured-data) with **correct syntax and semantics**.\nGood structured data [helps enhance a website's search result appearance](https://developers.google.com/search/docs/guides/enhance-site):\n\n\u003e \"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…\"\n\n## Usage\n\nLet's say you have a Rails app. First write plain-ruby code in a helper or controller. \n\nHere's what that'd look like in a controller. Instantiate\nthe structured data object you want in your web page:\n\n```ruby\n@my_org = Organization.new(\n  name:             'Public.Law',\n  founder:           Person.new(name: 'Robb Shecter'),\n  founding_date:     Date.new(2009, 3, 6),\n  founding_location: Place.new(address: 'Portland, OR'),\n  email:            'support@public.law',\n  telephone:        '+1 123 456 7890',\n  url:              'https://www.public.law',\n  logo:             'https://www.public.law/favicon-196x196.png',\n  same_as: [\n    'https://twitter.com/law_is_code',\n    'https://www.facebook.com/PublicDotLaw'\n    ]\n  )\n```\n\n...and then output it in a template:\n\n```html\n\u003c%= @my_org %\u003e\n```\n\n...you'll get this perfectly formatted structured data in your HTML:\n\n```html\n\u003cscript type=\"application/ld+json\"\u003e\n{\n  \"@context\": \"http://schema.org\",\n  \"@type\": \"Organization\",\n  \"name\": \"Public.Law\",\n  \"email\": \"support@public.law\",\n  \"telephone\": \"+1 123 456 7890\",\n  \"url\": \"https://www.public.law\",\n  \"logo\": \"https://www.public.law/favicon-196x196.png\",\n  \"foundingDate\": \"2009-03-06\",\n  \"founder\": {\n    \"@type\": \"Person\",\n    \"name\": \"Robb Shecter\"\n  },\n  \"foundingLocation\": {\n    \"@type\": \"Place\",\n    \"address\": \"Portland, OR\"\n  },\n  \"sameAs\": [\n    \"https://twitter.com/law_is_code\",\n    \"https://www.facebook.com/PublicDotLaw\"\n  ]\n}\n\u003c/script\u003e\n```\n\n### Principle: No silent failures\n\nWe coded the library this way because the data is embedded in the HTML - and it's a\npain in the butt to manually check for errors. In my case, I manage 500,000 unique\npages in my Rails app. There's _no way_ I could place error-free structured data in\nthem without automatic validation.\n\n`SchemaDotOrg` will validate your Ruby code, and if it's correct, will generate Schema.org JSON-LD markup when `#to_s`\nis called. If you, e.g., didn't add the correct attributes, you'll get a descriptive error message pointing\nyou to the problem.\n\nNotice how the `foundingDate` is in the required ISO-8601 format. In the same way, the `foundingLocation` is a `Place`\nwhich adds the proper `@type` attribute. All Ruby snake-case names have been converted to the Schema.org standard camel-case.\nEtc., etc.\n\n### You are prevented from creating invalid markup\n\nI make mistakes. So I wanted to know that if my page loads, the markup is good. I hate \"silent failures\".\n\nIf you use the wrong type or try to set an unknown attribute, SchemaDotOrg will\nrefuse to create the incorrect JSON-LD. Instead, you'll get a message explaining\nthe problem:\n\n```ruby\nPlace.new(address: 12345)\n# =\u003e ArgumentError: Address is class Integer, not String\n\nPlace.new(\n  address: '12345 Happy Street',\n  author:  'Hemmingway'\n)\n# =\u003e NoMethodError: undefined method `author'\n```\n\nIn my experience, I never get errors from the lib. I code it once, it works, and then\nI move on to other things.\n\n\u003e [!NOTE]\n\u003e This automatic validation comes from my [ValidatedObject gem](https://github.com/public-law/validated_object), which in turn,\n\u003e is a thin wrapper around ActiveRecord::Validations. So there's nothing magical going on here.\n\n## Supported Schema.org Types\n\nSee each type's RSpec for an example of how to use it.\n\n| Name                   | Schema.org Page                                         | RSpec Spec                                                                                                             | Source Code                                                                                                       |\n| ---------------------- | ------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |\n| 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)          |\n| 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)          |\n| 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)    |\n| 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)                  |\n| 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)            |\n| 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) |\n| 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)      |\n| 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)                |\n| 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)                 |\n| 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)                |\n| Offer                  | [Schema.org](https://schema.org/Offer)                  |                                                                                                                        | [Source](https://github.com/public-law/schema-dot-org/blob/master/lib/schema_dot_org/offer.rb)                    |\n| 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)             |\n| 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)                   |\n| 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)                    |\n| 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)           |\n| 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)                  |\n| 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)            |\n| 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)                 |\n\n## Examples\n\n### BreadcrumbList\n\nThe `make_breadcrumbs` convenience method creates a BreadcrumbList from a simple array of hashes:\n\n```ruby\nlinks = [\n  { name: 'Home',            url: 'https://example.com' },\n  { name: 'Books',           url: 'https://example.com/books' },\n  { name: 'Science Fiction', url: 'https://example.com/books/sci-fi' },\n  { name: 'Award Winners' }  # Last item typically has no URL\n]\n\nSchemaDotOrg\n  .make_breadcrumbs(links)\n  .to_s\n```\n\nproduces:\n\n```html\n\u003cscript type=\"application/ld+json\"\u003e\n{\n  \"@context\": \"https://schema.org\",\n  \"@type\": \"BreadcrumbList\",\n  \"itemListElement\": [\n    {\n      \"@type\": \"ListItem\",\n      \"position\": 1,\n      \"name\": \"Home\",\n      \"item\": \"https://example.com\"\n    },\n    {\n      \"@type\": \"ListItem\", \n      \"position\": 2,\n      \"name\": \"Books\",\n      \"item\": \"https://example.com/books\"\n    },\n    {\n      \"@type\": \"ListItem\",\n      \"position\": 3,\n      \"name\": \"Science Fiction\",\n      \"item\": \"https://example.com/books/sci-fi\"\n    },\n    {\n      \"@type\": \"ListItem\",\n      \"position\": 4,\n      \"name\": \"Award Winners\"\n    }\n  ]\n}\n\u003c/script\u003e\n```\n\nURLs are automatically validated - invalid URLs will raise an `ArgumentError` with a descriptive message.\n\n### WebSite\n\nExample with only the required attributes:\n\n```ruby\nWebSite.new(\n  name: 'Texas Public Law',\n  url:  'https://texas.public.law',\n)\n```\n\nWith the optional `SearchAction` to enable a [Sitelinks Searchbox](https://developers.google.com/search/docs/data-types/sitelinks-searchbox):\n\n```ruby\nWebSite.new(\n  name: 'Texas Public Law',\n  url:  'https://texas.public.law',\n  potential_action: SearchAction.new(\n    target: 'https://texas.public.law/?search={search_term_string}',\n    query_input: 'required name=search_term_string'\n  )\n)\n```\n\n\n## Installation\n\nAdd this line to your application's Gemfile:\n\n```ruby\ngem 'schema_dot_org'\n```\n\n## Development\n\nWe aim to make it as easy as possible to contribute new Schema.Org types. \nFor example, here's a large one, [Organization]([url](https://github.com/public-law/schema-dot-org/blob/master/lib/schema_dot_org/organization.rb)).\nThe declarative-style coding keeps it readable:\n\n```ruby\nrequire 'date'\n\nrequire_relative 'person'\nrequire_relative 'place'\nrequire_relative 'postal_address'\n\nmodule SchemaDotOrg\n  ##\n  # See https://schema.org/Organization\n  #\n  class Organization \u003c SchemaType\n    validated_attr :address,           type: PostalAddress,                       allow_nil: true\n    validated_attr :contact_points,    type: union(ContactPoint, [ContactPoint]), allow_nil: true\n    validated_attr :email,             type: String,                              allow_nil: true\n    validated_attr :founder,           type: Person,                              allow_nil: true\n    validated_attr :founding_date,     type: Date,                                allow_nil: true\n    validated_attr :founding_location, type: Place,                               allow_nil: true\n    validated_attr :legal_name,        type: String,                              allow_nil: true\n    validated_attr :same_as,           type: union(String, [String]),             allow_nil: true\n    validated_attr :slogan,            type: String,                              allow_nil: true\n    validated_attr :telephone,         type: String,                              allow_nil: true\n\n    ########################################\n    # Attributes that are required by Google\n    ########################################\n    validated_attr :logo,              type: String\n    validated_attr :name,              type: String\n    validated_attr :url,               type: String\n  end\nend\n```\n\nThe attributes are from the [Schema.org Organization spec](https://schema.org/Organization).\n\nAll Rails validations are available. These are just the attributes we've felt like\nadding. PR's are welcome if you want to add more. Also for more Schema.org types.\n\n\n## Contributing\n\nBug reports and pull requests are welcome on GitHub.\n\n## License\n\nThe gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpublic-law%2Fschema-dot-org","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpublic-law%2Fschema-dot-org","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpublic-law%2Fschema-dot-org/lists"}