better_seo 1.0.0.1 → 1.0.0.2
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/.rubocop.yml +30 -0
- data/.rubocop_todo.yml +360 -0
- data/CHANGELOG.md +44 -0
- data/README.md +7 -25
- data/lib/better_seo/analytics/google_analytics.rb +12 -12
- data/lib/better_seo/analytics/google_tag_manager.rb +7 -7
- data/lib/better_seo/configuration.rb +11 -5
- data/lib/better_seo/dsl/base.rb +1 -1
- data/lib/better_seo/dsl/open_graph.rb +2 -6
- data/lib/better_seo/dsl/twitter_cards.rb +5 -7
- data/lib/better_seo/generators/amp_generator.rb +8 -14
- data/lib/better_seo/generators/breadcrumbs_generator.rb +14 -13
- data/lib/better_seo/generators/canonical_url_manager.rb +8 -14
- data/lib/better_seo/generators/meta_tags_generator.rb +7 -6
- data/lib/better_seo/generators/open_graph_generator.rb +5 -5
- data/lib/better_seo/generators/robots_txt_generator.rb +5 -11
- data/lib/better_seo/generators/twitter_cards_generator.rb +4 -4
- data/lib/better_seo/image/optimizer.rb +2 -0
- data/lib/better_seo/rails/helpers/controller_helpers.rb +3 -1
- data/lib/better_seo/rails/helpers/seo_helper.rb +3 -7
- data/lib/better_seo/rails/helpers/structured_data_helper.rb +2 -2
- data/lib/better_seo/sitemap/generator.rb +1 -1
- data/lib/better_seo/sitemap/sitemap_index.rb +5 -5
- data/lib/better_seo/sitemap/url_entry.rb +9 -11
- data/lib/better_seo/structured_data/base.rb +2 -1
- data/lib/better_seo/structured_data/event.rb +1 -3
- data/lib/better_seo/structured_data/generator.rb +10 -10
- data/lib/better_seo/structured_data/recipe.rb +3 -4
- data/lib/better_seo/validators/seo_recommendations.rb +7 -7
- data/lib/better_seo/validators/seo_validator.rb +33 -23
- data/lib/better_seo/version.rb +1 -1
- data/lib/generators/better_seo/templates/better_seo.rb +2 -2
- metadata +3 -1
|
@@ -13,30 +13,37 @@ module BetterSeo
|
|
|
13
13
|
|
|
14
14
|
length = title.length
|
|
15
15
|
|
|
16
|
-
if length
|
|
16
|
+
if length.between?(TITLE_MIN_LENGTH, TITLE_MAX_LENGTH)
|
|
17
17
|
{ valid: true, score: 100, message: "Title length is optimal", length: length }
|
|
18
18
|
elsif length < TITLE_MIN_LENGTH
|
|
19
19
|
score = (length.to_f / TITLE_MIN_LENGTH * 70).to_i
|
|
20
|
-
{ valid: false, score: score,
|
|
20
|
+
{ valid: false, score: score,
|
|
21
|
+
message: "Title is too short (minimum #{TITLE_MIN_LENGTH} characters recommended)", length: length }
|
|
21
22
|
else
|
|
22
|
-
score = [100 - (length - TITLE_MAX_LENGTH) * 2, 50].max
|
|
23
|
-
{ valid: false, score: score,
|
|
23
|
+
score = [100 - ((length - TITLE_MAX_LENGTH) * 2), 50].max
|
|
24
|
+
{ valid: false, score: score,
|
|
25
|
+
message: "Title is too long (maximum #{TITLE_MAX_LENGTH} characters recommended)", length: length }
|
|
24
26
|
end
|
|
25
27
|
end
|
|
26
28
|
|
|
27
29
|
def check_description(description)
|
|
28
|
-
|
|
30
|
+
if description.nil? || description.empty?
|
|
31
|
+
return { valid: false, score: 0, message: "Description is required",
|
|
32
|
+
length: 0 }
|
|
33
|
+
end
|
|
29
34
|
|
|
30
35
|
length = description.length
|
|
31
36
|
|
|
32
|
-
if length
|
|
37
|
+
if length.between?(DESCRIPTION_MIN_LENGTH, DESCRIPTION_MAX_LENGTH)
|
|
33
38
|
{ valid: true, score: 100, message: "Description length is optimal", length: length }
|
|
34
39
|
elsif length < DESCRIPTION_MIN_LENGTH
|
|
35
40
|
score = (length.to_f / DESCRIPTION_MIN_LENGTH * 70).to_i
|
|
36
|
-
{ valid: false, score: score,
|
|
41
|
+
{ valid: false, score: score,
|
|
42
|
+
message: "Description is too short (minimum #{DESCRIPTION_MIN_LENGTH} characters recommended)", length: length }
|
|
37
43
|
else
|
|
38
44
|
score = [100 - (length - DESCRIPTION_MAX_LENGTH), 50].max
|
|
39
|
-
{ valid: false, score: score,
|
|
45
|
+
{ valid: false, score: score,
|
|
46
|
+
message: "Description is too long (maximum #{DESCRIPTION_MAX_LENGTH} characters recommended)", length: length }
|
|
40
47
|
end
|
|
41
48
|
end
|
|
42
49
|
|
|
@@ -57,11 +64,11 @@ module BetterSeo
|
|
|
57
64
|
total_headings: total
|
|
58
65
|
}
|
|
59
66
|
|
|
60
|
-
if h1_count
|
|
67
|
+
if h1_count.zero?
|
|
61
68
|
result.merge(valid: false, score: 50, message: "Missing H1 heading (exactly one H1 required)")
|
|
62
69
|
elsif h1_count > 1
|
|
63
70
|
result.merge(valid: false, score: 70, message: "Multiple H1 headings found (only one H1 recommended)")
|
|
64
|
-
elsif total
|
|
71
|
+
elsif total.zero?
|
|
65
72
|
result.merge(valid: false, score: 0, message: "No headings found")
|
|
66
73
|
else
|
|
67
74
|
result.merge(valid: true, score: 100, message: "Heading structure is optimal")
|
|
@@ -73,7 +80,10 @@ module BetterSeo
|
|
|
73
80
|
images = html.scan(/<img[^>]*>/)
|
|
74
81
|
total = images.size
|
|
75
82
|
|
|
76
|
-
|
|
83
|
+
if total.zero?
|
|
84
|
+
return { valid: true, score: 100, total_images: 0, images_with_alt: 0, images_without_alt: 0,
|
|
85
|
+
message: "No images to validate" }
|
|
86
|
+
end
|
|
77
87
|
|
|
78
88
|
# Count images with alt text
|
|
79
89
|
images_with_alt = images.count { |img| img =~ /alt=["'][^"']+["']/ }
|
|
@@ -95,7 +105,7 @@ module BetterSeo
|
|
|
95
105
|
|
|
96
106
|
def validate_page(html)
|
|
97
107
|
# Extract title
|
|
98
|
-
title_match = html.match(
|
|
108
|
+
title_match = html.match(%r{<title[^>]*>(.*?)</title>}m)
|
|
99
109
|
title = title_match ? title_match[1].strip : nil
|
|
100
110
|
|
|
101
111
|
# Extract meta description
|
|
@@ -110,10 +120,10 @@ module BetterSeo
|
|
|
110
120
|
|
|
111
121
|
# Calculate overall score (weighted average)
|
|
112
122
|
overall_score = (
|
|
113
|
-
title_result[:score] * 0.3 +
|
|
114
|
-
description_result[:score] * 0.3 +
|
|
115
|
-
headings_result[:score] * 0.2 +
|
|
116
|
-
images_result[:score] * 0.2
|
|
123
|
+
(title_result[:score] * 0.3) +
|
|
124
|
+
(description_result[:score] * 0.3) +
|
|
125
|
+
(headings_result[:score] * 0.2) +
|
|
126
|
+
(images_result[:score] * 0.2)
|
|
117
127
|
).to_i
|
|
118
128
|
|
|
119
129
|
# Collect issues
|
|
@@ -135,16 +145,16 @@ module BetterSeo
|
|
|
135
145
|
|
|
136
146
|
def generate_report(validation)
|
|
137
147
|
report = []
|
|
138
|
-
report << "=" * 60
|
|
148
|
+
report << ("=" * 60)
|
|
139
149
|
report << "SEO Validation Report"
|
|
140
|
-
report << "=" * 60
|
|
150
|
+
report << ("=" * 60)
|
|
141
151
|
report << ""
|
|
142
152
|
report << "Overall Score: #{validation[:overall_score]}/100"
|
|
143
153
|
report << ""
|
|
144
154
|
|
|
145
155
|
# Title section
|
|
146
156
|
report << "Title:"
|
|
147
|
-
report << " Status: #{validation[:title][:valid] ?
|
|
157
|
+
report << " Status: #{validation[:title][:valid] ? "✓" : "✗"}"
|
|
148
158
|
report << " Score: #{validation[:title][:score]}/100"
|
|
149
159
|
report << " Length: #{validation[:title][:length]} chars"
|
|
150
160
|
report << " Message: #{validation[:title][:message]}"
|
|
@@ -152,7 +162,7 @@ module BetterSeo
|
|
|
152
162
|
|
|
153
163
|
# Description section
|
|
154
164
|
report << "Description:"
|
|
155
|
-
report << " Status: #{validation[:description][:valid] ?
|
|
165
|
+
report << " Status: #{validation[:description][:valid] ? "✓" : "✗"}"
|
|
156
166
|
report << " Score: #{validation[:description][:score]}/100"
|
|
157
167
|
report << " Length: #{validation[:description][:length]} chars"
|
|
158
168
|
report << " Message: #{validation[:description][:message]}"
|
|
@@ -160,7 +170,7 @@ module BetterSeo
|
|
|
160
170
|
|
|
161
171
|
# Headings section
|
|
162
172
|
report << "Headings:"
|
|
163
|
-
report << " Status: #{validation[:headings][:valid] ?
|
|
173
|
+
report << " Status: #{validation[:headings][:valid] ? "✓" : "✗"}"
|
|
164
174
|
report << " Score: #{validation[:headings][:score]}/100"
|
|
165
175
|
report << " H1 Count: #{validation[:headings][:h1_count]}"
|
|
166
176
|
report << " Total Headings: #{validation[:headings][:total_headings]}"
|
|
@@ -169,7 +179,7 @@ module BetterSeo
|
|
|
169
179
|
|
|
170
180
|
# Images section
|
|
171
181
|
report << "Images:"
|
|
172
|
-
report << " Status: #{validation[:images][:valid] ?
|
|
182
|
+
report << " Status: #{validation[:images][:valid] ? "✓" : "✗"}"
|
|
173
183
|
report << " Score: #{validation[:images][:score]}/100"
|
|
174
184
|
report << " Total Images: #{validation[:images][:total_images]}"
|
|
175
185
|
report << " With Alt: #{validation[:images][:images_with_alt]}"
|
|
@@ -186,7 +196,7 @@ module BetterSeo
|
|
|
186
196
|
report << ""
|
|
187
197
|
end
|
|
188
198
|
|
|
189
|
-
report << "=" * 60
|
|
199
|
+
report << ("=" * 60)
|
|
190
200
|
|
|
191
201
|
report.join("\n")
|
|
192
202
|
end
|
data/lib/better_seo/version.rb
CHANGED
|
@@ -4,14 +4,14 @@ BetterSeo.configure do |config|
|
|
|
4
4
|
# Site-wide settings
|
|
5
5
|
config.site_name = "My Site"
|
|
6
6
|
config.default_locale = :en
|
|
7
|
-
config.available_locales = [
|
|
7
|
+
config.available_locales = %i[en it fr de es]
|
|
8
8
|
|
|
9
9
|
# Meta tags configuration
|
|
10
10
|
config.meta_tags.default_title = "Default Title"
|
|
11
11
|
config.meta_tags.title_separator = " | "
|
|
12
12
|
config.meta_tags.append_site_name = true
|
|
13
13
|
config.meta_tags.default_description = "Default description for your website"
|
|
14
|
-
config.meta_tags.default_keywords = [
|
|
14
|
+
config.meta_tags.default_keywords = %w[keyword1 keyword2 keyword3]
|
|
15
15
|
config.meta_tags.default_author = "Your Name or Company"
|
|
16
16
|
|
|
17
17
|
# Open Graph configuration
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: better_seo
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0.0.
|
|
4
|
+
version: 1.0.0.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- alessiobussolari
|
|
@@ -77,6 +77,7 @@ extra_rdoc_files: []
|
|
|
77
77
|
files:
|
|
78
78
|
- ".rspec"
|
|
79
79
|
- ".rubocop.yml"
|
|
80
|
+
- ".rubocop_todo.yml"
|
|
80
81
|
- CHANGELOG.md
|
|
81
82
|
- CODE_OF_CONDUCT.md
|
|
82
83
|
- LICENSE.txt
|
|
@@ -145,6 +146,7 @@ metadata:
|
|
|
145
146
|
homepage_uri: https://github.com/alessiobussolari/better_seo
|
|
146
147
|
source_code_uri: https://github.com/alessiobussolari/better_seo
|
|
147
148
|
changelog_uri: https://github.com/alessiobussolari/better_seo/blob/main/CHANGELOG.md
|
|
149
|
+
rubygems_mfa_required: 'true'
|
|
148
150
|
post_install_message:
|
|
149
151
|
rdoc_options: []
|
|
150
152
|
require_paths:
|