better_seo 0.11.0 → 0.13.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 +4 -4
- data/CHANGELOG.md +90 -0
- data/README.md +465 -11
- data/lib/better_seo/version.rb +1 -1
- data/lib/better_seo.rb +5 -0
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 42834acb5d5dca21a12b20288b28544bd5112aac2fe8a05dbf3123707f1f21fe
|
|
4
|
+
data.tar.gz: 8efa2fd4287fbf0078d57691148c2cdc78e2f03a18c5af2eb96fc6819d32c5d6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 934a6db489cbda29d885011c889d268b66858b9d202d5c561907543365a639547c7e9bc39cd2dc0acc529e4fba4c9f9eb21de10fb76cdb7211c15c4622249073
|
|
7
|
+
data.tar.gz: d5ceb959972b3e687140a87c87c649525d0844abaffb1ddd316259eaa4cd82b7b5780152a92e06120c8ab7ff46fdce33f1c2449f8f225321a92958f87d8895bc
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,96 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.13.0] - 2025-01-23
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- Advanced SEO Tools for validation and content management
|
|
14
|
+
- **Robots.txt Generator** (`BetterSeo::Generators::RobotsTxtGenerator`)
|
|
15
|
+
- `add_rule(user_agent, allow:, disallow:)` - Add robot directives
|
|
16
|
+
- `set_crawl_delay(user_agent, seconds)` - Set crawl delay for bots
|
|
17
|
+
- `add_sitemap(url)` - Add sitemap references
|
|
18
|
+
- `clear` - Remove all rules and sitemaps
|
|
19
|
+
- `to_text` - Generate robots.txt content
|
|
20
|
+
- `write_to_file(path)` - Write robots.txt to file
|
|
21
|
+
- Support for multiple user agents (*, Googlebot, Bingbot, etc.)
|
|
22
|
+
- Allow/Disallow path directives
|
|
23
|
+
- Automatic directory creation
|
|
24
|
+
- Method chaining for fluent API
|
|
25
|
+
- **SEO Validator** (`BetterSeo::Validators::SeoValidator`)
|
|
26
|
+
- `check_title(text)` - Validate title length (30-60 chars optimal)
|
|
27
|
+
- `check_description(text)` - Validate description length (120-160 chars optimal)
|
|
28
|
+
- `check_headings(html)` - Validate H1-H6 structure
|
|
29
|
+
- `check_images(html)` - Validate image alt text presence
|
|
30
|
+
- `validate_page(html)` - Complete page validation
|
|
31
|
+
- `generate_report(validation)` - Human-readable SEO report
|
|
32
|
+
- Overall SEO score (0-100) with weighted components
|
|
33
|
+
- Detailed issue tracking and recommendations
|
|
34
|
+
- Warning levels for sub-optimal content
|
|
35
|
+
- HTML parsing for meta tags extraction
|
|
36
|
+
|
|
37
|
+
### Enhanced
|
|
38
|
+
- Validators module introduced for SEO quality checks
|
|
39
|
+
- Comprehensive validation rules following SEO best practices
|
|
40
|
+
- Detailed error messages with actionable recommendations
|
|
41
|
+
|
|
42
|
+
### Test Coverage
|
|
43
|
+
- 858 tests passing (+47 from v0.12.0)
|
|
44
|
+
- 96.7% code coverage (1668/1725 lines)
|
|
45
|
+
- 47 new tests across SEO tools:
|
|
46
|
+
- Robots.txt Generator: 25 tests
|
|
47
|
+
- SEO Validator: 22 tests
|
|
48
|
+
|
|
49
|
+
## [0.12.0] - 2025-01-23
|
|
50
|
+
|
|
51
|
+
### Added
|
|
52
|
+
- Advanced HTML Generators for modern web applications
|
|
53
|
+
- **BreadcrumbsGenerator** (`BetterSeo::Generators::BreadcrumbsGenerator`)
|
|
54
|
+
- `add_item(name, url)` - Add single breadcrumb item
|
|
55
|
+
- `add_items(array)` - Add multiple items at once
|
|
56
|
+
- `clear` - Remove all items
|
|
57
|
+
- `to_html(schema:, nav_class:, list_class:)` - Generate HTML breadcrumbs
|
|
58
|
+
- `to_json_ld` - Generate JSON-LD structured data
|
|
59
|
+
- `to_script_tag` - Generate script tag with JSON-LD
|
|
60
|
+
- Schema.org microdata support with `schema: true` option
|
|
61
|
+
- Custom CSS classes for nav and list elements
|
|
62
|
+
- Automatic position numbering for structured data
|
|
63
|
+
- Current page support (items without URLs)
|
|
64
|
+
- HTML entity escaping for security
|
|
65
|
+
- **AMP Generator** (`BetterSeo::Generators::AmpGenerator`)
|
|
66
|
+
- `to_boilerplate` - Generate required AMP boilerplate CSS
|
|
67
|
+
- `to_amp_script_tag` - Generate AMP runtime script tag
|
|
68
|
+
- `to_meta_tags` - Generate canonical and OG meta tags
|
|
69
|
+
- `to_structured_data` - Generate JSON-LD script tag
|
|
70
|
+
- `to_custom_css(css)` - Wrap custom CSS in amp-custom style tag
|
|
71
|
+
- Support for canonical URL, title, description, image
|
|
72
|
+
- Structured data integration for AMP pages
|
|
73
|
+
- Complete AMP HTML page support
|
|
74
|
+
- **Canonical URL Manager** (`BetterSeo::Generators::CanonicalUrlManager`)
|
|
75
|
+
- `to_html` - Generate canonical link HTML tag
|
|
76
|
+
- `to_http_header` - Generate Link HTTP header
|
|
77
|
+
- `validate!` - Validate canonical URL format and structure
|
|
78
|
+
- URL normalization features:
|
|
79
|
+
- Remove trailing slashes (preserves root URL)
|
|
80
|
+
- Remove fragment identifiers automatically
|
|
81
|
+
- Optional query parameter removal
|
|
82
|
+
- Optional URL lowercasing
|
|
83
|
+
- Validation for absolute URLs only
|
|
84
|
+
- HTTP/HTTPS protocol validation
|
|
85
|
+
- HTML entity escaping
|
|
86
|
+
|
|
87
|
+
### Enhanced
|
|
88
|
+
- HTML Generators section in README with comprehensive examples
|
|
89
|
+
- Documentation for all three new generators
|
|
90
|
+
- Rails integration examples for each generator
|
|
91
|
+
|
|
92
|
+
### Test Coverage
|
|
93
|
+
- 811 tests passing (+69 from v0.11.0)
|
|
94
|
+
- 96.41% code coverage (1506/1562 lines)
|
|
95
|
+
- 69 new tests across advanced generators:
|
|
96
|
+
- BreadcrumbsGenerator: 21 tests
|
|
97
|
+
- AMP Generator: 22 tests
|
|
98
|
+
- Canonical URL Manager: 26 tests
|
|
99
|
+
|
|
10
100
|
## [0.11.0] - 2025-01-23
|
|
11
101
|
|
|
12
102
|
### 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
|
-
[](https://github.com/yourusername/better_seo)
|
|
6
|
+
[](https://github.com/yourusername/better_seo)
|
|
7
7
|
[](https://www.ruby-lang.org)
|
|
8
8
|
[](https://rubyonrails.org)
|
|
9
9
|
|
|
10
10
|
## Features
|
|
11
11
|
|
|
12
|
-
### ✅ Implemented (v0.
|
|
12
|
+
### ✅ Implemented (v0.13.0)
|
|
13
13
|
|
|
14
14
|
- **Core Configuration System**
|
|
15
15
|
- Singleton configuration with block-style setup
|
|
@@ -25,10 +25,13 @@ A comprehensive SEO gem for Ruby and Rails applications. BetterSeo provides a cl
|
|
|
25
25
|
- Fluent interface with method chaining
|
|
26
26
|
- Automatic validation (title/description length, required fields)
|
|
27
27
|
|
|
28
|
-
- **HTML Generators**
|
|
28
|
+
- **HTML Generators** - Advanced generators for modern web
|
|
29
29
|
- **MetaTagsGenerator**: Converts DSL to HTML meta tags
|
|
30
30
|
- **OpenGraphGenerator**: Converts DSL to Open Graph meta tags
|
|
31
31
|
- **TwitterCardsGenerator**: Converts DSL to Twitter Card meta tags
|
|
32
|
+
- **BreadcrumbsGenerator**: HTML breadcrumb navigation with Schema.org support
|
|
33
|
+
- **AMP Generator**: Accelerated Mobile Pages (AMP) support
|
|
34
|
+
- **Canonical URL Manager**: Canonical URL normalization and management
|
|
32
35
|
- HTML entity escaping for security
|
|
33
36
|
- Integration with DSL builders
|
|
34
37
|
|
|
@@ -76,16 +79,11 @@ A comprehensive SEO gem for Ruby and Rails applications. BetterSeo provides a cl
|
|
|
76
79
|
|
|
77
80
|
### 🚧 Planned
|
|
78
81
|
|
|
79
|
-
- **Advanced
|
|
80
|
-
- Breadcrumbs HTML generator
|
|
81
|
-
- AMP HTML generator
|
|
82
|
-
- Canonical URL management
|
|
83
|
-
|
|
84
|
-
- **Advanced Features** (v0.6.0+)
|
|
82
|
+
- **Advanced Features** (v0.13.0+)
|
|
85
83
|
- robots.txt generator
|
|
86
84
|
- Image optimization with WebP conversion
|
|
87
|
-
- Structured data builders (Organization, Person, Product, etc.)
|
|
88
85
|
- SEO validators and recommendations
|
|
86
|
+
- Performance monitoring and analytics integration
|
|
89
87
|
|
|
90
88
|
## Installation
|
|
91
89
|
|
|
@@ -1532,6 +1530,462 @@ all_tags = BetterSeo::StructuredData::Generator.generate_script_tags([
|
|
|
1532
1530
|
- **Standards Compliant**: Follows Schema.org specifications
|
|
1533
1531
|
- **Easy Integration**: Works seamlessly with Rails views and helpers
|
|
1534
1532
|
|
|
1533
|
+
---
|
|
1534
|
+
|
|
1535
|
+
## Advanced Generators
|
|
1536
|
+
|
|
1537
|
+
### Breadcrumbs Generator
|
|
1538
|
+
|
|
1539
|
+
Generate HTML breadcrumb navigation with Schema.org structured data support.
|
|
1540
|
+
|
|
1541
|
+
#### Basic Usage
|
|
1542
|
+
|
|
1543
|
+
```ruby
|
|
1544
|
+
generator = BetterSeo::Generators::BreadcrumbsGenerator.new
|
|
1545
|
+
generator.add_item("Home", "/")
|
|
1546
|
+
generator.add_item("Products", "/products")
|
|
1547
|
+
generator.add_item("Laptops", "/products/laptops")
|
|
1548
|
+
generator.add_item("MacBook Pro", nil) # Current page (no link)
|
|
1549
|
+
|
|
1550
|
+
# Generate HTML breadcrumbs
|
|
1551
|
+
html = generator.to_html
|
|
1552
|
+
# <nav class="breadcrumb" aria-label="breadcrumb">
|
|
1553
|
+
# <ol class="breadcrumb">
|
|
1554
|
+
# <li class="breadcrumb-item">
|
|
1555
|
+
# <a href="/">Home</a>
|
|
1556
|
+
# </li>
|
|
1557
|
+
# ...
|
|
1558
|
+
# </ol>
|
|
1559
|
+
# </nav>
|
|
1560
|
+
|
|
1561
|
+
# Generate JSON-LD structured data
|
|
1562
|
+
json_ld = generator.to_json_ld
|
|
1563
|
+
script_tag = generator.to_script_tag
|
|
1564
|
+
```
|
|
1565
|
+
|
|
1566
|
+
#### With Schema.org Markup
|
|
1567
|
+
|
|
1568
|
+
```ruby
|
|
1569
|
+
# Generate breadcrumbs with microdata
|
|
1570
|
+
html = generator.to_html(schema: true)
|
|
1571
|
+
# Includes itemscope, itemtype, itemprop attributes for rich snippets
|
|
1572
|
+
```
|
|
1573
|
+
|
|
1574
|
+
#### Custom Styling
|
|
1575
|
+
|
|
1576
|
+
```ruby
|
|
1577
|
+
html = generator.to_html(
|
|
1578
|
+
nav_class: "my-breadcrumb-nav",
|
|
1579
|
+
list_class: "my-breadcrumb-list"
|
|
1580
|
+
)
|
|
1581
|
+
```
|
|
1582
|
+
|
|
1583
|
+
#### Rails Integration
|
|
1584
|
+
|
|
1585
|
+
```erb
|
|
1586
|
+
<!-- app/views/layouts/application.html.erb -->
|
|
1587
|
+
<%
|
|
1588
|
+
breadcrumbs = BetterSeo::Generators::BreadcrumbsGenerator.new
|
|
1589
|
+
breadcrumbs.add_item("Home", root_path)
|
|
1590
|
+
breadcrumbs.add_item("Blog", blog_path)
|
|
1591
|
+
breadcrumbs.add_item(@post.title, nil)
|
|
1592
|
+
%>
|
|
1593
|
+
|
|
1594
|
+
<%= raw breadcrumbs.to_html(schema: true) %>
|
|
1595
|
+
<%= raw breadcrumbs.to_script_tag %>
|
|
1596
|
+
```
|
|
1597
|
+
|
|
1598
|
+
#### Multiple Items at Once
|
|
1599
|
+
|
|
1600
|
+
```ruby
|
|
1601
|
+
generator.add_items([
|
|
1602
|
+
{ name: "Home", url: "/" },
|
|
1603
|
+
{ name: "Products", url: "/products" },
|
|
1604
|
+
{ name: "Laptops", url: "/products/laptops" }
|
|
1605
|
+
])
|
|
1606
|
+
```
|
|
1607
|
+
|
|
1608
|
+
---
|
|
1609
|
+
|
|
1610
|
+
### AMP Generator
|
|
1611
|
+
|
|
1612
|
+
Generate Accelerated Mobile Pages (AMP) HTML components.
|
|
1613
|
+
|
|
1614
|
+
#### Basic Usage
|
|
1615
|
+
|
|
1616
|
+
```ruby
|
|
1617
|
+
amp = BetterSeo::Generators::AmpGenerator.new(
|
|
1618
|
+
canonical_url: "https://example.com/article",
|
|
1619
|
+
title: "My Article Title",
|
|
1620
|
+
description: "Article description",
|
|
1621
|
+
image: "https://example.com/image.jpg"
|
|
1622
|
+
)
|
|
1623
|
+
|
|
1624
|
+
# AMP boilerplate CSS
|
|
1625
|
+
boilerplate = amp.to_boilerplate
|
|
1626
|
+
|
|
1627
|
+
# AMP runtime script
|
|
1628
|
+
amp_script = amp.to_amp_script_tag
|
|
1629
|
+
# <script async src="https://cdn.ampproject.org/v0.js"></script>
|
|
1630
|
+
|
|
1631
|
+
# Meta tags
|
|
1632
|
+
meta_tags = amp.to_meta_tags
|
|
1633
|
+
# Includes canonical, og:title, og:description, og:image
|
|
1634
|
+
```
|
|
1635
|
+
|
|
1636
|
+
#### Complete AMP Page
|
|
1637
|
+
|
|
1638
|
+
```erb
|
|
1639
|
+
<!doctype html>
|
|
1640
|
+
<html ⚡>
|
|
1641
|
+
<head>
|
|
1642
|
+
<meta charset="utf-8">
|
|
1643
|
+
<meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
|
|
1644
|
+
|
|
1645
|
+
<%= raw amp.to_meta_tags %>
|
|
1646
|
+
<%= raw amp.to_amp_script_tag %>
|
|
1647
|
+
<%= raw amp.to_boilerplate %>
|
|
1648
|
+
|
|
1649
|
+
<% custom_css = "body { font-family: Arial; } h1 { color: #333; }" %>
|
|
1650
|
+
<%= raw amp.to_custom_css(custom_css) %>
|
|
1651
|
+
</head>
|
|
1652
|
+
<body>
|
|
1653
|
+
<!-- Your AMP content -->
|
|
1654
|
+
</body>
|
|
1655
|
+
</html>
|
|
1656
|
+
```
|
|
1657
|
+
|
|
1658
|
+
#### With Structured Data
|
|
1659
|
+
|
|
1660
|
+
```ruby
|
|
1661
|
+
article_data = {
|
|
1662
|
+
"@context" => "https://schema.org",
|
|
1663
|
+
"@type" => "Article",
|
|
1664
|
+
"headline" => "My Article",
|
|
1665
|
+
"author" => { "@type" => "Person", "name" => "John Doe" }
|
|
1666
|
+
}
|
|
1667
|
+
|
|
1668
|
+
amp.structured_data = article_data
|
|
1669
|
+
script = amp.to_structured_data
|
|
1670
|
+
# <script type="application/ld+json">
|
|
1671
|
+
# { "@context": "https://schema.org", "@type": "Article", ... }
|
|
1672
|
+
# </script>
|
|
1673
|
+
```
|
|
1674
|
+
|
|
1675
|
+
#### Rails Controller Integration
|
|
1676
|
+
|
|
1677
|
+
```ruby
|
|
1678
|
+
class ArticlesController < ApplicationController
|
|
1679
|
+
def amp
|
|
1680
|
+
@article = Article.find(params[:id])
|
|
1681
|
+
|
|
1682
|
+
@amp = BetterSeo::Generators::AmpGenerator.new(
|
|
1683
|
+
canonical_url: article_url(@article),
|
|
1684
|
+
title: @article.title,
|
|
1685
|
+
description: @article.excerpt,
|
|
1686
|
+
image: @article.featured_image_url
|
|
1687
|
+
)
|
|
1688
|
+
|
|
1689
|
+
render layout: 'amp'
|
|
1690
|
+
end
|
|
1691
|
+
end
|
|
1692
|
+
```
|
|
1693
|
+
|
|
1694
|
+
---
|
|
1695
|
+
|
|
1696
|
+
### Canonical URL Manager
|
|
1697
|
+
|
|
1698
|
+
Manage and normalize canonical URLs with validation.
|
|
1699
|
+
|
|
1700
|
+
#### Basic Usage
|
|
1701
|
+
|
|
1702
|
+
```ruby
|
|
1703
|
+
manager = BetterSeo::Generators::CanonicalUrlManager.new("https://example.com/page")
|
|
1704
|
+
|
|
1705
|
+
# Generate HTML link tag
|
|
1706
|
+
html = manager.to_html
|
|
1707
|
+
# <link rel="canonical" href="https://example.com/page">
|
|
1708
|
+
|
|
1709
|
+
# Generate HTTP header
|
|
1710
|
+
header = manager.to_http_header
|
|
1711
|
+
# <https://example.com/page>; rel="canonical"
|
|
1712
|
+
|
|
1713
|
+
# Validate URL
|
|
1714
|
+
manager.validate! # Raises ValidationError if invalid
|
|
1715
|
+
```
|
|
1716
|
+
|
|
1717
|
+
#### URL Normalization
|
|
1718
|
+
|
|
1719
|
+
```ruby
|
|
1720
|
+
manager = BetterSeo::Generators::CanonicalUrlManager.new
|
|
1721
|
+
|
|
1722
|
+
# Removes trailing slashes
|
|
1723
|
+
manager.url = "https://example.com/page/"
|
|
1724
|
+
manager.url # => "https://example.com/page"
|
|
1725
|
+
|
|
1726
|
+
# Removes fragment identifiers
|
|
1727
|
+
manager.url = "https://example.com/page#section"
|
|
1728
|
+
manager.url # => "https://example.com/page"
|
|
1729
|
+
|
|
1730
|
+
# Optional: Remove query parameters
|
|
1731
|
+
manager.remove_query_params = true
|
|
1732
|
+
manager.url = "https://example.com/page?utm_source=twitter&ref=123"
|
|
1733
|
+
manager.url # => "https://example.com/page"
|
|
1734
|
+
|
|
1735
|
+
# Optional: Lowercase URL
|
|
1736
|
+
manager.lowercase = true
|
|
1737
|
+
manager.url = "https://Example.com/Page"
|
|
1738
|
+
manager.url # => "https://example.com/page"
|
|
1739
|
+
```
|
|
1740
|
+
|
|
1741
|
+
#### Rails Integration
|
|
1742
|
+
|
|
1743
|
+
```ruby
|
|
1744
|
+
# Controller
|
|
1745
|
+
class ArticlesController < ApplicationController
|
|
1746
|
+
def show
|
|
1747
|
+
@article = Article.find(params[:id])
|
|
1748
|
+
|
|
1749
|
+
canonical = BetterSeo::Generators::CanonicalUrlManager.new
|
|
1750
|
+
canonical.remove_query_params = true
|
|
1751
|
+
canonical.url = article_url(@article)
|
|
1752
|
+
|
|
1753
|
+
response.headers['Link'] = canonical.to_http_header
|
|
1754
|
+
@canonical_tag = canonical.to_html
|
|
1755
|
+
end
|
|
1756
|
+
end
|
|
1757
|
+
|
|
1758
|
+
# View (app/views/articles/show.html.erb)
|
|
1759
|
+
<head>
|
|
1760
|
+
<%= raw @canonical_tag %>
|
|
1761
|
+
</head>
|
|
1762
|
+
```
|
|
1763
|
+
|
|
1764
|
+
#### Advanced Normalization
|
|
1765
|
+
|
|
1766
|
+
```ruby
|
|
1767
|
+
manager = BetterSeo::Generators::CanonicalUrlManager.new
|
|
1768
|
+
manager.remove_query_params = true
|
|
1769
|
+
manager.lowercase = true
|
|
1770
|
+
manager.url = "https://Example.com/Page/?utm_source=google#section"
|
|
1771
|
+
|
|
1772
|
+
manager.url # => "https://example.com/page"
|
|
1773
|
+
manager.validate! # => true
|
|
1774
|
+
```
|
|
1775
|
+
|
|
1776
|
+
#### Error Handling
|
|
1777
|
+
|
|
1778
|
+
```ruby
|
|
1779
|
+
manager = BetterSeo::Generators::CanonicalUrlManager.new
|
|
1780
|
+
|
|
1781
|
+
# Relative URLs not allowed
|
|
1782
|
+
manager.url = "/page"
|
|
1783
|
+
manager.validate! # Raises: "Canonical URL must be absolute: /page"
|
|
1784
|
+
|
|
1785
|
+
# Invalid URL format
|
|
1786
|
+
manager.url = "not a url"
|
|
1787
|
+
manager.validate! # Raises: "Invalid URL format: not a url"
|
|
1788
|
+
|
|
1789
|
+
# URL is required
|
|
1790
|
+
manager.url = nil
|
|
1791
|
+
manager.validate! # Raises: "URL is required"
|
|
1792
|
+
```
|
|
1793
|
+
|
|
1794
|
+
---
|
|
1795
|
+
|
|
1796
|
+
## SEO Tools
|
|
1797
|
+
|
|
1798
|
+
### Robots.txt Generator
|
|
1799
|
+
|
|
1800
|
+
Generate robots.txt files to control search engine crawler access.
|
|
1801
|
+
|
|
1802
|
+
#### Basic Usage
|
|
1803
|
+
|
|
1804
|
+
```ruby
|
|
1805
|
+
robots = BetterSeo::Generators::RobotsTxtGenerator.new
|
|
1806
|
+
|
|
1807
|
+
# Allow all bots except specific paths
|
|
1808
|
+
robots.add_rule("*", disallow: ["/admin", "/api/private", "/tmp"])
|
|
1809
|
+
|
|
1810
|
+
# Add sitemap
|
|
1811
|
+
robots.add_sitemap("https://example.com/sitemap.xml")
|
|
1812
|
+
|
|
1813
|
+
# Generate robots.txt content
|
|
1814
|
+
text = robots.to_text
|
|
1815
|
+
# User-agent: *
|
|
1816
|
+
# Disallow: /admin
|
|
1817
|
+
# Disallow: /api/private
|
|
1818
|
+
# Disallow: /tmp
|
|
1819
|
+
#
|
|
1820
|
+
# Sitemap: https://example.com/sitemap.xml
|
|
1821
|
+
```
|
|
1822
|
+
|
|
1823
|
+
#### Multiple User Agents
|
|
1824
|
+
|
|
1825
|
+
```ruby
|
|
1826
|
+
robots = BetterSeo::Generators::RobotsTxtGenerator.new
|
|
1827
|
+
|
|
1828
|
+
# Rules for all bots
|
|
1829
|
+
robots.add_rule("*", allow: "/", disallow: "/admin")
|
|
1830
|
+
|
|
1831
|
+
# Specific rules for Googlebot
|
|
1832
|
+
robots.add_rule("Googlebot", allow: "/api/public", disallow: "/temp")
|
|
1833
|
+
|
|
1834
|
+
# Crawl delay for aggressive bots
|
|
1835
|
+
robots.add_rule("Bingbot", disallow: "/admin")
|
|
1836
|
+
robots.set_crawl_delay("Bingbot", 2)
|
|
1837
|
+
|
|
1838
|
+
text = robots.to_text
|
|
1839
|
+
```
|
|
1840
|
+
|
|
1841
|
+
#### Write to File
|
|
1842
|
+
|
|
1843
|
+
```ruby
|
|
1844
|
+
robots = BetterSeo::Generators::RobotsTxtGenerator.new
|
|
1845
|
+
robots.add_rule("*", disallow: ["/admin", "/private"])
|
|
1846
|
+
robots.add_sitemap("https://example.com/sitemap.xml")
|
|
1847
|
+
|
|
1848
|
+
# Write to public directory
|
|
1849
|
+
robots.write_to_file(Rails.root.join('public', 'robots.txt'))
|
|
1850
|
+
```
|
|
1851
|
+
|
|
1852
|
+
#### Rails Controller Integration
|
|
1853
|
+
|
|
1854
|
+
```ruby
|
|
1855
|
+
# app/controllers/robots_controller.rb
|
|
1856
|
+
class RobotsController < ApplicationController
|
|
1857
|
+
def index
|
|
1858
|
+
robots = BetterSeo::Generators::RobotsTxtGenerator.new
|
|
1859
|
+
|
|
1860
|
+
if Rails.env.production?
|
|
1861
|
+
robots.add_rule("*", disallow: ["/admin", "/api/private"])
|
|
1862
|
+
robots.add_sitemap("#{request.base_url}/sitemap.xml")
|
|
1863
|
+
else
|
|
1864
|
+
# Block all bots in non-production
|
|
1865
|
+
robots.add_rule("*", disallow: "/")
|
|
1866
|
+
end
|
|
1867
|
+
|
|
1868
|
+
render plain: robots.to_text, content_type: "text/plain"
|
|
1869
|
+
end
|
|
1870
|
+
end
|
|
1871
|
+
|
|
1872
|
+
# config/routes.rb
|
|
1873
|
+
get '/robots.txt', to: 'robots#index'
|
|
1874
|
+
```
|
|
1875
|
+
|
|
1876
|
+
---
|
|
1877
|
+
|
|
1878
|
+
### SEO Validator
|
|
1879
|
+
|
|
1880
|
+
Validate and score your pages for SEO best practices.
|
|
1881
|
+
|
|
1882
|
+
#### Basic Usage
|
|
1883
|
+
|
|
1884
|
+
```ruby
|
|
1885
|
+
validator = BetterSeo::Validators::SeoValidator.new
|
|
1886
|
+
|
|
1887
|
+
# Check individual elements
|
|
1888
|
+
title_result = validator.check_title("My Awesome SEO-Friendly Page Title")
|
|
1889
|
+
# => { valid: true, score: 100, message: "Title length is optimal", length: 35 }
|
|
1890
|
+
|
|
1891
|
+
desc_result = validator.check_description("This is a comprehensive meta description...")
|
|
1892
|
+
# => { valid: true, score: 100, message: "Description length is optimal", length: 145 }
|
|
1893
|
+
```
|
|
1894
|
+
|
|
1895
|
+
#### Validate Complete Page
|
|
1896
|
+
|
|
1897
|
+
```ruby
|
|
1898
|
+
validator = BetterSeo::Validators::SeoValidator.new
|
|
1899
|
+
|
|
1900
|
+
html = <<~HTML
|
|
1901
|
+
<!DOCTYPE html>
|
|
1902
|
+
<html>
|
|
1903
|
+
<head>
|
|
1904
|
+
<title>Best Ruby SEO Gem for Rails Applications</title>
|
|
1905
|
+
<meta name="description" content="BetterSeo provides comprehensive SEO tools for Ruby on Rails including meta tags, structured data, sitemaps, and validators.">
|
|
1906
|
+
</head>
|
|
1907
|
+
<body>
|
|
1908
|
+
<h1>BetterSeo: Complete SEO Solution</h1>
|
|
1909
|
+
<img src="logo.png" alt="BetterSeo Logo">
|
|
1910
|
+
<h2>Features</h2>
|
|
1911
|
+
<h2>Getting Started</h2>
|
|
1912
|
+
</body>
|
|
1913
|
+
</html>
|
|
1914
|
+
HTML
|
|
1915
|
+
|
|
1916
|
+
result = validator.validate_page(html)
|
|
1917
|
+
# => {
|
|
1918
|
+
# overall_score: 95,
|
|
1919
|
+
# title: { valid: true, score: 100, ... },
|
|
1920
|
+
# description: { valid: true, score: 100, ... },
|
|
1921
|
+
# headings: { valid: true, score: 100, h1_count: 1, ... },
|
|
1922
|
+
# images: { valid: true, score: 100, ... },
|
|
1923
|
+
# issues: []
|
|
1924
|
+
# }
|
|
1925
|
+
```
|
|
1926
|
+
|
|
1927
|
+
#### Generate SEO Report
|
|
1928
|
+
|
|
1929
|
+
```ruby
|
|
1930
|
+
validator = BetterSeo::Validators::SeoValidator.new
|
|
1931
|
+
result = validator.validate_page(html)
|
|
1932
|
+
|
|
1933
|
+
report = validator.generate_report(result)
|
|
1934
|
+
puts report
|
|
1935
|
+
# ============================================================
|
|
1936
|
+
# SEO Validation Report
|
|
1937
|
+
# ============================================================
|
|
1938
|
+
#
|
|
1939
|
+
# Overall Score: 95/100
|
|
1940
|
+
#
|
|
1941
|
+
# Title:
|
|
1942
|
+
# Status: ✓
|
|
1943
|
+
# Score: 100/100
|
|
1944
|
+
# Length: 45 chars
|
|
1945
|
+
# Message: Title length is optimal
|
|
1946
|
+
#
|
|
1947
|
+
# Description:
|
|
1948
|
+
# Status: ✓
|
|
1949
|
+
# Score: 100/100
|
|
1950
|
+
# ...
|
|
1951
|
+
```
|
|
1952
|
+
|
|
1953
|
+
#### Rails Integration
|
|
1954
|
+
|
|
1955
|
+
```ruby
|
|
1956
|
+
# app/services/seo_validator_service.rb
|
|
1957
|
+
class SeoValidatorService
|
|
1958
|
+
def self.validate_page_seo(url)
|
|
1959
|
+
html = fetch_page_html(url)
|
|
1960
|
+
validator = BetterSeo::Validators::SeoValidator.new
|
|
1961
|
+
validator.validate_page(html)
|
|
1962
|
+
end
|
|
1963
|
+
|
|
1964
|
+
def self.audit_site
|
|
1965
|
+
pages = Page.published.pluck(:url)
|
|
1966
|
+
validator = BetterSeo::Validators::SeoValidator.new
|
|
1967
|
+
|
|
1968
|
+
results = pages.map do |url|
|
|
1969
|
+
html = fetch_page_html(url)
|
|
1970
|
+
validation = validator.validate_page(html)
|
|
1971
|
+
{ url: url, score: validation[:overall_score], issues: validation[:issues] }
|
|
1972
|
+
end
|
|
1973
|
+
|
|
1974
|
+
results.sort_by { |r| r[:score] }
|
|
1975
|
+
end
|
|
1976
|
+
end
|
|
1977
|
+
```
|
|
1978
|
+
|
|
1979
|
+
#### Validation Rules
|
|
1980
|
+
|
|
1981
|
+
- **Title**: 30-60 characters optimal
|
|
1982
|
+
- **Description**: 120-160 characters optimal
|
|
1983
|
+
- **Headings**: Exactly one H1 tag required
|
|
1984
|
+
- **Images**: All images must have alt text
|
|
1985
|
+
- **Overall Score**: Weighted average (Title: 30%, Description: 30%, Headings: 20%, Images: 20%)
|
|
1986
|
+
|
|
1987
|
+
---
|
|
1988
|
+
|
|
1535
1989
|
## Configuration Reference
|
|
1536
1990
|
|
|
1537
1991
|
### Global Configuration
|
data/lib/better_seo/version.rb
CHANGED
data/lib/better_seo.rb
CHANGED
|
@@ -13,6 +13,11 @@ require_relative "better_seo/dsl/twitter_cards"
|
|
|
13
13
|
require_relative "better_seo/generators/meta_tags_generator"
|
|
14
14
|
require_relative "better_seo/generators/open_graph_generator"
|
|
15
15
|
require_relative "better_seo/generators/twitter_cards_generator"
|
|
16
|
+
require_relative "better_seo/generators/breadcrumbs_generator"
|
|
17
|
+
require_relative "better_seo/generators/amp_generator"
|
|
18
|
+
require_relative "better_seo/generators/canonical_url_manager"
|
|
19
|
+
require_relative "better_seo/generators/robots_txt_generator"
|
|
20
|
+
require_relative "better_seo/validators/seo_validator"
|
|
16
21
|
require_relative "better_seo/sitemap/url_entry"
|
|
17
22
|
require_relative "better_seo/sitemap/builder"
|
|
18
23
|
require_relative "better_seo/sitemap/generator"
|