better_seo 0.5.0 → 0.6.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 96812d57f991f56ae85d042ed90d67cd804da41be917f557c9035b7103704fa0
4
- data.tar.gz: ba04b33847262251dbce411840acee273e7f36c3f25e3b02a6fd2aaacf88bbe9
3
+ metadata.gz: 4b1f457db06f6ed1a5654363c639448945eb0c8ee11f311203333edf3de5b499
4
+ data.tar.gz: bbb3f5e0f831a1f3437b1dd171b4e7c8cc953fc654b102670037da19cc96ae73
5
5
  SHA512:
6
- metadata.gz: 587ba80330156dc5a305ea2d92831939fa9f80b6341bdb1052d639d371b8892d9827ddd0ce24b4b07c0c67714aec87151dcc31bc515031aee055a10703d3bf0f
7
- data.tar.gz: 8dfe3c3526d621ee904535484e70529c68550d2388f289408a40f044651f154f6cb424f8715967d3d9dcaf8aa652f48bdb0ddda1e505c882c37f8fe01c9a1dbc
6
+ metadata.gz: '0978f9a96df030f0b10c10e409c9938c7cca9d5b881212c10135de040f6e51cbd1631f5b6d76ffe9af9efad722336d4f522edb7abf6872d7abd86ae2e516f7ce'
7
+ data.tar.gz: e3fcdde3228d074d75f3a47abcfb81c5145c827191512642745254df0c93c8be1f7a2f82c0d9aaed783c64951dc1b753b436e928fd29d6fc22fce6091b97ea7b
data/CHANGELOG.md CHANGED
@@ -7,6 +7,37 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.6.0] - 2025-01-23
11
+
12
+ ### Added
13
+ - Structured Data (JSON-LD) support with comprehensive Schema.org implementation
14
+ - `StructuredData::Base` - Generic base class for all structured data types
15
+ - `StructuredData::Organization` - Company/organization information with full schema support
16
+ - `StructuredData::Article` - Blog posts, news articles with author/publisher metadata
17
+ - `StructuredData::Person` - Author profiles, team members with social links
18
+ - `StructuredData::Generator` - Helper class with factory methods
19
+ - Structured data features
20
+ - Fluent API with method chaining for all types
21
+ - Automatic nested object handling (Person within Article, etc.)
22
+ - JSON-LD generation with `to_json` and `to_script_tag` methods
23
+ - Schema.org compliant output format
24
+ - Address handling with PostalAddress schema
25
+ - Social profile links with sameAs property
26
+ - Rails integration patterns
27
+ - View helpers for structured data
28
+ - Layout integration examples
29
+ - Complete production examples
30
+ - Comprehensive documentation
31
+ - 300+ lines of structured data documentation in README
32
+ - Complete examples for Organization, Article, Person
33
+ - Rails integration patterns and helper methods
34
+ - Nested data examples
35
+
36
+ ### Test Coverage
37
+ - 491 tests passing (+107 from v0.5.0)
38
+ - 99.64% code coverage (820/823 lines)
39
+ - 117 new tests for structured data functionality
40
+
10
41
  ## [0.5.0] - 2025-01-23
11
42
 
12
43
  ### Added
data/README.md CHANGED
@@ -2,14 +2,14 @@
2
2
 
3
3
  A comprehensive SEO gem for Ruby and Rails applications. BetterSeo provides a clean, fluent DSL for managing meta tags, Open Graph, Twitter Cards, structured data, sitemaps, and more.
4
4
 
5
- [![Tests](https://img.shields.io/badge/tests-384%20passing-brightgreen)](https://github.com/yourusername/better_seo)
6
- [![Coverage](https://img.shields.io/badge/coverage-99.71%25-brightgreen)](https://github.com/yourusername/better_seo)
5
+ [![Tests](https://img.shields.io/badge/tests-491%20passing-brightgreen)](https://github.com/yourusername/better_seo)
6
+ [![Coverage](https://img.shields.io/badge/coverage-99.64%25-brightgreen)](https://github.com/yourusername/better_seo)
7
7
  [![Ruby](https://img.shields.io/badge/ruby-%3E%3D%203.0.0-red)](https://www.ruby-lang.org)
8
8
  [![Rails](https://img.shields.io/badge/rails-%3E%3D%206.1-red)](https://rubyonrails.org)
9
9
 
10
10
  ## Features
11
11
 
12
- ### ✅ Implemented (v0.5.0)
12
+ ### ✅ Implemented (v0.6.0)
13
13
 
14
14
  - **Core Configuration System**
15
15
  - Singleton configuration with block-style setup
@@ -48,19 +48,37 @@ A comprehensive SEO gem for Ruby and Rails applications. BetterSeo provides a cl
48
48
  - **Validation**: Automatic URL validation (format, protocol)
49
49
  - **Method Chaining**: Fluent interface for adding multiple URLs
50
50
 
51
+ - **Structured Data (JSON-LD)**
52
+ - **Base Class**: Generic structured data with full Schema.org support
53
+ - **Organization**: Company/organization information with address, social profiles
54
+ - **Article**: Blog posts, news articles with author, publisher, metadata
55
+ - **Person**: Author profiles, team members with job title, social links
56
+ - **Generator Helper**: Factory methods and batch script tag generation
57
+ - **Nested Data**: Automatic handling of complex object relationships
58
+ - **JSON-LD Output**: Valid Schema.org JSON-LD format
59
+ - **Rails Integration**: View helpers and layout integration
60
+
51
61
  ### 🚧 Planned
52
62
 
53
- - **Advanced Generators** (v0.6.0)
54
- - Schema.org JSON-LD generator
55
- - Breadcrumbs generator
63
+ - **Additional Structured Data Types** (v0.7.0)
64
+ - Product (e-commerce with price, availability)
65
+ - BreadcrumbList (navigation breadcrumbs)
66
+ - LocalBusiness (physical locations)
67
+ - Event (conferences, webinars)
68
+ - FAQPage, HowTo, Recipe
69
+
70
+ - **Advanced Generators** (v0.7.0)
71
+ - Breadcrumbs HTML generator
56
72
  - AMP HTML generator
73
+ - Canonical URL management
57
74
 
58
- - **Advanced Rails Integration** (v0.6.0)
75
+ - **Advanced Rails Integration** (v0.7.0)
59
76
  - Controller helpers for setting page SEO
60
77
  - Railtie for automatic initialization
61
78
  - Generator for initializer file
79
+ - Automatic meta tags from model attributes
62
80
 
63
- - **Advanced Sitemap Features** (v0.6.0)
81
+ - **Advanced Sitemap Features** (v0.7.0)
64
82
  - Multi-language sitemap support (hreflang)
65
83
  - Sitemap index for large sites (50,000+ URLs)
66
84
  - Image/video sitemap extensions
@@ -79,7 +97,7 @@ A comprehensive SEO gem for Ruby and Rails applications. BetterSeo provides a cl
79
97
  Add this line to your application's Gemfile:
80
98
 
81
99
  ```ruby
82
- gem 'better_seo', '~> 0.5.0'
100
+ gem 'better_seo', '~> 0.6.0'
83
101
  ```
84
102
 
85
103
  And then execute:
@@ -99,7 +117,7 @@ gem install better_seo
99
117
  Add this line to your application's Gemfile:
100
118
 
101
119
  ```ruby
102
- gem 'better_seo', git: 'https://github.com/alessiobussolari/better_seo.git', tag: 'v0.5.0'
120
+ gem 'better_seo', git: 'https://github.com/alessiobussolari/better_seo.git', tag: 'v0.6.0'
103
121
  ```
104
122
 
105
123
  Or clone and build locally:
@@ -108,7 +126,7 @@ Or clone and build locally:
108
126
  git clone https://github.com/alessiobussolari/better_seo.git
109
127
  cd better_seo
110
128
  gem build better_seo.gemspec
111
- gem install better_seo-0.5.0.gem
129
+ gem install better_seo-0.6.0.gem
112
130
  ```
113
131
 
114
132
  ## Quick Start
@@ -1020,6 +1038,304 @@ end
1020
1038
  # SitemapGeneratorService.generate
1021
1039
  ```
1022
1040
 
1041
+ ### 7. Structured Data (JSON-LD)
1042
+
1043
+ BetterSeo provides comprehensive support for Schema.org structured data using JSON-LD format, helping search engines better understand your content.
1044
+
1045
+ #### Basic Usage
1046
+
1047
+ Create structured data objects and generate JSON-LD script tags:
1048
+
1049
+ ```ruby
1050
+ # Create an Organization
1051
+ org = BetterSeo::StructuredData::Organization.new
1052
+ org.name("Acme Corporation")
1053
+ org.url("https://www.acme.com")
1054
+ org.logo("https://www.acme.com/logo.png")
1055
+ org.description("Leading provider of innovative solutions")
1056
+
1057
+ # Generate JSON-LD script tag
1058
+ org.to_script_tag
1059
+ # <script type="application/ld+json">
1060
+ # {
1061
+ # "@context": "https://schema.org",
1062
+ # "@type": "Organization",
1063
+ # "name": "Acme Corporation",
1064
+ # ...
1065
+ # }
1066
+ # </script>
1067
+ ```
1068
+
1069
+ #### Available Types
1070
+
1071
+ **Organization** - Company/organization information:
1072
+
1073
+ ```ruby
1074
+ org = BetterSeo::StructuredData::Organization.new
1075
+ org.name("Tech Innovations Inc")
1076
+ org.url("https://techinnovations.com")
1077
+ org.logo("https://techinnovations.com/logo.png")
1078
+ org.description("Innovative technology solutions")
1079
+ org.email("contact@techinnovations.com")
1080
+ org.telephone("+1-555-0100")
1081
+ org.address(
1082
+ street: "123 Tech Boulevard",
1083
+ city: "San Francisco",
1084
+ region: "CA",
1085
+ postal_code: "94105",
1086
+ country: "US"
1087
+ )
1088
+ org.same_as([
1089
+ "https://twitter.com/techinnovations",
1090
+ "https://linkedin.com/company/techinnovations"
1091
+ ])
1092
+ org.founding_date("2015-03-20")
1093
+ ```
1094
+
1095
+ **Article** - Blog posts, news articles, content:
1096
+
1097
+ ```ruby
1098
+ article = BetterSeo::StructuredData::Article.new
1099
+ article.headline("The Future of Web Development")
1100
+ article.description("An in-depth analysis of emerging trends")
1101
+ article.image("https://example.com/article-image.jpg")
1102
+ article.author("Jane Smith") # Or use Person object
1103
+ article.date_published("2024-01-15T09:00:00Z")
1104
+ article.date_modified("2024-01-20T14:30:00Z")
1105
+ article.url("https://example.com/articles/future-of-web-dev")
1106
+ article.word_count(2500)
1107
+ article.keywords(["Web Development", "Technology", "Trends"])
1108
+ article.article_section("Technology")
1109
+ ```
1110
+
1111
+ **Person** - Author profiles, team members:
1112
+
1113
+ ```ruby
1114
+ person = BetterSeo::StructuredData::Person.new
1115
+ person.name("Dr. Jane Smith")
1116
+ person.given_name("Jane")
1117
+ person.family_name("Smith")
1118
+ person.email("jane@example.com")
1119
+ person.url("https://janesmith.dev")
1120
+ person.image("https://janesmith.dev/profile.jpg")
1121
+ person.job_title("Chief Technology Officer")
1122
+ person.telephone("+1-555-0199")
1123
+ person.same_as([
1124
+ "https://twitter.com/janesmith",
1125
+ "https://linkedin.com/in/janesmith"
1126
+ ])
1127
+ ```
1128
+
1129
+ #### Method Chaining
1130
+
1131
+ All structured data classes support fluent method chaining:
1132
+
1133
+ ```ruby
1134
+ org = BetterSeo::StructuredData::Organization.new
1135
+ .name("Acme Corp")
1136
+ .url("https://acme.com")
1137
+ .logo("https://acme.com/logo.png")
1138
+ .description("Innovation at its finest")
1139
+ ```
1140
+
1141
+ #### Nested Structured Data
1142
+
1143
+ Combine multiple structured data objects:
1144
+
1145
+ ```ruby
1146
+ # Create publisher organization
1147
+ publisher = BetterSeo::StructuredData::Organization.new
1148
+ publisher.name("Tech Publishing Co")
1149
+ publisher.logo("https://techpub.com/logo.png")
1150
+
1151
+ # Create author person
1152
+ author = BetterSeo::StructuredData::Person.new
1153
+ author.name("Jane Smith")
1154
+ author.email("jane@techpub.com")
1155
+ author.url("https://janesmith.dev")
1156
+
1157
+ # Create article with nested data
1158
+ article = BetterSeo::StructuredData::Article.new
1159
+ article.headline("Introduction to Ruby on Rails")
1160
+ article.description("A comprehensive guide for beginners")
1161
+ article.image("https://example.com/rails-guide.jpg")
1162
+ article.author(author) # Nested Person
1163
+ article.publisher(publisher) # Nested Organization
1164
+ article.date_published("2024-01-15")
1165
+
1166
+ # Generates nested JSON-LD automatically
1167
+ article.to_script_tag
1168
+ ```
1169
+
1170
+ #### Using the Generator Helper
1171
+
1172
+ The Generator class provides convenient factory methods:
1173
+
1174
+ ```ruby
1175
+ # Create with block
1176
+ org = BetterSeo::StructuredData::Generator.organization do |o|
1177
+ o.name("Acme Corp")
1178
+ o.url("https://acme.com")
1179
+ o.logo("https://acme.com/logo.png")
1180
+ end
1181
+
1182
+ article = BetterSeo::StructuredData::Generator.article do |a|
1183
+ a.headline("Amazing Article")
1184
+ a.author("John Doe")
1185
+ a.date_published("2024-01-15")
1186
+ end
1187
+
1188
+ person = BetterSeo::StructuredData::Generator.person do |p|
1189
+ p.name("John Doe")
1190
+ p.email("john@example.com")
1191
+ end
1192
+
1193
+ # Generate multiple script tags at once
1194
+ tags = BetterSeo::StructuredData::Generator.generate_script_tags([org, article, person])
1195
+ # Returns all three script tags joined with newlines
1196
+ ```
1197
+
1198
+ #### Rails Integration
1199
+
1200
+ Add structured data to your Rails views:
1201
+
1202
+ ```erb
1203
+ <%# app/views/articles/show.html.erb %>
1204
+ <%
1205
+ author = BetterSeo::StructuredData::Generator.person do |p|
1206
+ p.name(@article.author.name)
1207
+ p.email(@article.author.email)
1208
+ p.url(@article.author.website)
1209
+ end
1210
+
1211
+ article_sd = BetterSeo::StructuredData::Generator.article do |a|
1212
+ a.headline(@article.title)
1213
+ a.description(@article.excerpt)
1214
+ a.image(url_for(@article.cover_image))
1215
+ a.author(author)
1216
+ a.date_published(@article.published_at.iso8601)
1217
+ a.date_modified(@article.updated_at.iso8601)
1218
+ a.url(article_url(@article))
1219
+ a.word_count(@article.word_count)
1220
+ a.keywords(@article.tags.pluck(:name))
1221
+ end
1222
+ %>
1223
+
1224
+ <%== article_sd.to_script_tag %>
1225
+ ```
1226
+
1227
+ Or in a helper:
1228
+
1229
+ ```ruby
1230
+ # app/helpers/structured_data_helper.rb
1231
+ module StructuredDataHelper
1232
+ def article_structured_data(article)
1233
+ author = BetterSeo::StructuredData::Generator.person do |p|
1234
+ p.name(article.author.name)
1235
+ p.url(author_url(article.author))
1236
+ end
1237
+
1238
+ article_sd = BetterSeo::StructuredData::Generator.article do |a|
1239
+ a.headline(article.title)
1240
+ a.description(article.excerpt)
1241
+ a.author(author)
1242
+ a.date_published(article.published_at.iso8601)
1243
+ a.url(article_url(article))
1244
+ end
1245
+
1246
+ article_sd.to_script_tag.html_safe
1247
+ end
1248
+
1249
+ def organization_structured_data
1250
+ org = BetterSeo::StructuredData::Generator.organization do |o|
1251
+ o.name(Rails.application.config.site_name)
1252
+ o.url(root_url)
1253
+ o.logo(image_url('logo.png'))
1254
+ o.same_as([
1255
+ "https://twitter.com/yourcompany",
1256
+ "https://facebook.com/yourcompany"
1257
+ ])
1258
+ end
1259
+
1260
+ org.to_script_tag.html_safe
1261
+ end
1262
+ end
1263
+ ```
1264
+
1265
+ Then in your layout:
1266
+
1267
+ ```erb
1268
+ <%# app/views/layouts/application.html.erb %>
1269
+ <head>
1270
+ ...
1271
+ <%= organization_structured_data %>
1272
+ </head>
1273
+ ```
1274
+
1275
+ And in article views:
1276
+
1277
+ ```erb
1278
+ <%# app/views/articles/show.html.erb %>
1279
+ <%= article_structured_data(@article) %>
1280
+ ```
1281
+
1282
+ #### Complete Example
1283
+
1284
+ ```ruby
1285
+ # Create complete structured data for a blog article
1286
+ publisher = BetterSeo::StructuredData::Generator.organization do |o|
1287
+ o.name("Tech Blog Publishing")
1288
+ o.url("https://techblog.com")
1289
+ o.logo("https://techblog.com/logo.png")
1290
+ end
1291
+
1292
+ author = BetterSeo::StructuredData::Generator.person do |p|
1293
+ p.name("Dr. Sarah Johnson")
1294
+ p.email("sarah@techblog.com")
1295
+ p.url("https://sarahjohnson.dev")
1296
+ p.job_title("Senior Technology Writer")
1297
+ end
1298
+
1299
+ article = BetterSeo::StructuredData::Generator.article do |a|
1300
+ a.headline("The Complete Guide to Ruby on Rails in 2024")
1301
+ a.description("Everything you need to know about Rails")
1302
+ a.image([
1303
+ "https://techblog.com/images/rails-2024-1.jpg",
1304
+ "https://techblog.com/images/rails-2024-2.jpg"
1305
+ ])
1306
+ a.author(author)
1307
+ a.publisher(publisher)
1308
+ a.date_published("2024-01-15T09:00:00Z")
1309
+ a.date_modified("2024-01-20T15:30:00Z")
1310
+ a.url("https://techblog.com/rails-complete-guide-2024")
1311
+ a.word_count(3500)
1312
+ a.keywords(["Ruby on Rails", "Web Development", "2024"])
1313
+ a.article_section("Programming")
1314
+ end
1315
+
1316
+ # Get JSON-LD
1317
+ json_ld = article.to_json
1318
+
1319
+ # Get script tag for HTML
1320
+ script_tag = article.to_script_tag
1321
+
1322
+ # Or generate all at once
1323
+ all_tags = BetterSeo::StructuredData::Generator.generate_script_tags([
1324
+ publisher,
1325
+ author,
1326
+ article
1327
+ ])
1328
+ ```
1329
+
1330
+ #### Benefits
1331
+
1332
+ - **SEO Enhancement**: Help search engines understand your content better
1333
+ - **Rich Snippets**: Enable rich results in search results (ratings, images, etc.)
1334
+ - **Type Safety**: Fluent API with method chaining
1335
+ - **Nested Data**: Automatic handling of complex relationships
1336
+ - **Standards Compliant**: Follows Schema.org specifications
1337
+ - **Easy Integration**: Works seamlessly with Rails views and helpers
1338
+
1023
1339
  ## Configuration Reference
1024
1340
 
1025
1341
  ### Global Configuration
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module BetterSeo
4
- VERSION = "0.5.0"
4
+ VERSION = "0.6.0"
5
5
  end
data/lib/better_seo.rb CHANGED
@@ -17,6 +17,11 @@ require_relative "better_seo/rails/helpers/seo_helper"
17
17
  require_relative "better_seo/sitemap/url_entry"
18
18
  require_relative "better_seo/sitemap/builder"
19
19
  require_relative "better_seo/sitemap/generator"
20
+ require_relative "better_seo/structured_data/base"
21
+ require_relative "better_seo/structured_data/organization"
22
+ require_relative "better_seo/structured_data/article"
23
+ require_relative "better_seo/structured_data/person"
24
+ require_relative "better_seo/structured_data/generator"
20
25
 
21
26
  module BetterSeo
22
27
  class << self
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: better_seo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - alessiobussolari
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-10-22 00:00:00.000000000 Z
11
+ date: 2025-10-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport