rails-index-now 0.1.0 → 0.1.1
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/README.md +72 -40
- data/app/controllers/rails/index/now/verification_controller.rb +23 -0
- data/config/routes.rb +6 -0
- data/lib/rails/index/now/configuration.rb +6 -1
- data/lib/rails/index/now/generators/templates/index_now.rb +6 -1
- data/lib/rails/index/now/railtie.rb +14 -2
- data/lib/rails/index/now/version.rb +1 -1
- data/lib/rails/index/now.rb +1 -1
- metadata +3 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 46fec440350448dd22519a7740c457ab8da3d36e5baa02507a947cf4ee2d3c53
|
4
|
+
data.tar.gz: d10aef18ee049858221c75570cd0b656f34a14b80bda87cecfd380cafc9f49dd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 32f839f9bc654915fef22d051fbfce5404b4efedd0e6298d490a6a909876b855f64c7294f70867abecca8b211accf2eb8a24b24eaeab3bf136b53cc6870232f8
|
7
|
+
data.tar.gz: ccd77df77bbb88de39aad14c83bcaec5f274220c7d745b4859118a305c259196a5fb54ede22ddd26593ea79420547477e3830e5627479d558d7aca1730e1d9f5
|
data/README.md
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
[](https://badge.fury.io/rb/rails-index-now)
|
4
4
|
[](https://github.com/aleksdavtian/rails-index-now/actions)
|
5
5
|
|
6
|
-
A modern,
|
6
|
+
A modern, plug-and-play Rails Engine for seamless integration with Microsoft's IndexNow protocol. Get your content indexed by search engines instantly, with automatic API key verification and zero manual configuration.
|
7
7
|
|
8
8
|
## What is IndexNow?
|
9
9
|
|
@@ -19,6 +19,13 @@ A modern, lightweight Rails gem for seamless integration with Microsoft's IndexN
|
|
19
19
|
|
20
20
|
Traditional search engine indexing relies on crawlers periodically visiting your site. With IndexNow, you proactively tell search engines exactly what has changed, when it changed, making the indexing process nearly instantaneous.
|
21
21
|
|
22
|
+
### Why This Rails Engine?
|
23
|
+
|
24
|
+
- **🚀 Plug-and-Play**: No manual controller or route setup required
|
25
|
+
- **🔐 Automatic Verification**: The engine automatically serves your API key file at the correct URL
|
26
|
+
- **⚡ Zero Configuration**: Just add the gem, run the generator, and you're ready
|
27
|
+
- **🛡️ Production Ready**: Built-in error handling, logging, and environment controls
|
28
|
+
|
22
29
|
## Installation
|
23
30
|
|
24
31
|
Add this line to your application's Gemfile:
|
@@ -39,42 +46,59 @@ Or install it yourself as:
|
|
39
46
|
gem install rails-index-now
|
40
47
|
```
|
41
48
|
|
42
|
-
##
|
49
|
+
## Quick Setup
|
50
|
+
|
51
|
+
### 1. Install the Gem
|
43
52
|
|
44
|
-
|
53
|
+
Add to your Gemfile and run `bundle install`:
|
54
|
+
|
55
|
+
```ruby
|
56
|
+
gem 'rails-index-now'
|
57
|
+
```
|
58
|
+
|
59
|
+
### 2. Generate Configuration
|
45
60
|
|
46
61
|
```bash
|
47
62
|
rails generate index_now:install
|
48
63
|
```
|
49
64
|
|
50
|
-
|
65
|
+
### 3. Configure Your API Key
|
66
|
+
|
67
|
+
Get your free API key from [Bing IndexNow](https://www.bing.com/indexnow/getstarted) and add it to your environment:
|
68
|
+
|
69
|
+
```bash
|
70
|
+
# .env or your environment
|
71
|
+
INDEXNOW_API_KEY=your_api_key_here
|
72
|
+
```
|
73
|
+
|
74
|
+
**That's it!** The engine automatically:
|
75
|
+
- ✅ Serves your API key at `/your_api_key_here.txt` (for IndexNow verification)
|
76
|
+
- ✅ Handles all routing and controller logic
|
77
|
+
- ✅ Configures sensible defaults for all environments
|
78
|
+
|
79
|
+
### Configuration Options
|
80
|
+
|
81
|
+
The generator creates `config/initializers/index_now.rb` with these options:
|
51
82
|
|
52
83
|
```ruby
|
53
84
|
Rails::Index::Now.configure do |config|
|
54
85
|
# Required: Your IndexNow API key
|
55
|
-
|
56
|
-
|
86
|
+
config.api_key = ENV.fetch("INDEXNOW_API_KEY", nil)
|
87
|
+
|
88
|
+
# Required: Key file name (automatically set from your API key)
|
89
|
+
config.key_file_name = "#{ENV.fetch('INDEXNOW_API_KEY', 'your-api-key')}.txt"
|
57
90
|
|
58
91
|
# Optional: Set a specific host for all submissions
|
59
|
-
#
|
60
|
-
config.host = "yourdomain.com"
|
92
|
+
# config.host = "yourdomain.com"
|
61
93
|
|
62
|
-
# Optional: Disable IndexNow in specific environments
|
63
|
-
# Recommended for test and development environments
|
94
|
+
# Optional: Disable IndexNow in specific environments
|
64
95
|
config.disabled = Rails.env.test? || Rails.env.development?
|
65
96
|
|
66
97
|
# Optional: Set a custom logger
|
67
|
-
#
|
68
|
-
config.logger = Rails.logger
|
98
|
+
# config.logger = Rails.logger
|
69
99
|
end
|
70
100
|
```
|
71
101
|
|
72
|
-
### Getting Your IndexNow API Key
|
73
|
-
|
74
|
-
1. Visit [IndexNow.org](https://www.indexnow.org/)
|
75
|
-
2. Generate a free API key
|
76
|
-
3. Add the key to your environment variables or Rails credentials
|
77
|
-
|
78
102
|
## Usage
|
79
103
|
|
80
104
|
### Basic Usage
|
@@ -92,12 +116,12 @@ Rails::Index::Now.submit([
|
|
92
116
|
])
|
93
117
|
```
|
94
118
|
|
95
|
-
### Background Processing (
|
119
|
+
### Background Processing (Optional)
|
96
120
|
|
97
|
-
For production applications, use background jobs to avoid blocking web requests:
|
121
|
+
For production applications, use background jobs to avoid blocking web requests. **Note: This requires ActiveJob to be available in your application.**
|
98
122
|
|
99
123
|
```ruby
|
100
|
-
# Submit URLs asynchronously using ActiveJob
|
124
|
+
# Submit URLs asynchronously using ActiveJob (requires ActiveJob)
|
101
125
|
Rails::Index::Now.submit_async("https://yourdomain.com/articles/123")
|
102
126
|
|
103
127
|
Rails::Index::Now.submit_async([
|
@@ -106,26 +130,23 @@ Rails::Index::Now.submit_async([
|
|
106
130
|
])
|
107
131
|
```
|
108
132
|
|
109
|
-
The gem works seamlessly with any ActiveJob backend (Sidekiq, SolidQueue, GoodJob, etc.).
|
133
|
+
The gem works seamlessly with any ActiveJob backend (Sidekiq, SolidQueue, GoodJob, etc.) when ActiveJob is available.
|
110
134
|
|
111
|
-
###
|
135
|
+
### Rails Model Integration
|
112
136
|
|
113
|
-
|
137
|
+
The magic happens when you integrate IndexNow with your Rails models. Here's a complete example:
|
114
138
|
|
115
139
|
```ruby
|
116
140
|
class Article < ApplicationRecord
|
117
|
-
#
|
141
|
+
# Automatically notify search engines when articles are created or updated
|
118
142
|
after_commit :submit_to_index_now, on: [:create, :update]
|
119
143
|
|
120
|
-
# Also submit when articles are published
|
121
|
-
after_commit :submit_to_index_now, if: :saved_change_to_published_at?
|
122
|
-
|
123
144
|
private
|
124
145
|
|
125
146
|
def submit_to_index_now
|
126
147
|
return unless published? && Rails.env.production?
|
127
148
|
|
128
|
-
#
|
149
|
+
# The engine handles everything - just submit the URL!
|
129
150
|
Rails::Index::Now.submit_async(article_url)
|
130
151
|
end
|
131
152
|
|
@@ -138,12 +159,18 @@ class Article < ApplicationRecord
|
|
138
159
|
end
|
139
160
|
```
|
140
161
|
|
162
|
+
**What happens automatically:**
|
163
|
+
1. 🔥 Your article gets saved
|
164
|
+
2. 🚀 `after_commit` triggers IndexNow submission
|
165
|
+
3. 🎯 Search engines are notified within seconds
|
166
|
+
4. ✅ Your content appears in search results faster
|
167
|
+
|
141
168
|
### Advanced Usage
|
142
169
|
|
143
|
-
For more complex scenarios, you can also use the job directly:
|
170
|
+
For more complex scenarios, you can also use the job directly (requires ActiveJob):
|
144
171
|
|
145
172
|
```ruby
|
146
|
-
# Use the provided ActiveJob directly
|
173
|
+
# Use the provided ActiveJob directly (requires ActiveJob)
|
147
174
|
Rails::Index::Now::SubmitJob.perform_later([
|
148
175
|
"https://yourdomain.com/page1",
|
149
176
|
"https://yourdomain.com/page2"
|
@@ -153,6 +180,8 @@ Rails::Index::Now::SubmitJob.perform_later([
|
|
153
180
|
Rails::Index::Now::SubmitJob.perform_now(["https://yourdomain.com/page"])
|
154
181
|
```
|
155
182
|
|
183
|
+
**Note:** If ActiveJob is not available, use the synchronous `submit` method instead.
|
184
|
+
|
156
185
|
### Error Handling
|
157
186
|
|
158
187
|
The gem includes comprehensive error handling and logging:
|
@@ -169,22 +198,25 @@ Rails::Index::Now.submit("invalid-url")
|
|
169
198
|
|
170
199
|
## Framework Compatibility
|
171
200
|
|
172
|
-
This
|
201
|
+
This Rails Engine requires:
|
173
202
|
|
174
|
-
- **Rails
|
203
|
+
- **Rails 5.0+** (for Rails Engine support)
|
175
204
|
- **Ruby 2.7+**
|
205
|
+
- **ActiveJob** (optional, only needed for `submit_async` functionality)
|
176
206
|
|
177
|
-
The
|
207
|
+
The engine automatically integrates with your Rails application:
|
178
208
|
|
179
|
-
-
|
180
|
-
-
|
181
|
-
-
|
182
|
-
-
|
209
|
+
- **🔄 Automatic Routing**: No need to manually add routes - the engine handles it
|
210
|
+
- **🎛️ Controller Integration**: Built-in controller serves API key verification file
|
211
|
+
- **⚡ ActiveJob**: Optional - enables `submit_async` method with any backend (Sidekiq, SolidQueue, etc.)
|
212
|
+
- **📝 Smart Logging**: Uses Rails.logger with helpful [IndexNow] prefixes
|
213
|
+
- **🌍 Environment Awareness**: Easy to disable in development/test environments
|
214
|
+
- **🛠️ Rails Generators**: One-command setup with `rails generate index_now:install`
|
183
215
|
|
184
216
|
## Performance Considerations
|
185
217
|
|
186
|
-
- **Asynchronous by Design**: The `submit_async` method queues jobs to avoid blocking web requests
|
187
|
-
- **Lightweight**: Zero
|
218
|
+
- **Asynchronous by Design**: The `submit_async` method queues jobs to avoid blocking web requests (when ActiveJob is available)
|
219
|
+
- **Lightweight**: Zero runtime dependencies - uses only Ruby standard library
|
188
220
|
- **Efficient**: Batches multiple URLs in single API calls when possible
|
189
221
|
- **Fault Tolerant**: Gracefully handles network failures and API errors
|
190
222
|
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Rails
|
4
|
+
module Index
|
5
|
+
module Now
|
6
|
+
class VerificationController < ActionController::Base
|
7
|
+
# Skip CSRF protection for this simple text response
|
8
|
+
skip_before_action :verify_authenticity_token, only: [:index_now_key]
|
9
|
+
|
10
|
+
def index_now_key
|
11
|
+
config = Rails::Index::Now.configuration
|
12
|
+
|
13
|
+
unless config.engine_valid?
|
14
|
+
render plain: "IndexNow configuration invalid", status: :internal_server_error
|
15
|
+
return
|
16
|
+
end
|
17
|
+
|
18
|
+
render plain: config.api_key, content_type: "text/plain"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/config/routes.rb
ADDED
@@ -4,13 +4,14 @@ module Rails
|
|
4
4
|
module Index
|
5
5
|
module Now
|
6
6
|
class Configuration
|
7
|
-
attr_accessor :api_key, :host, :disabled, :logger
|
7
|
+
attr_accessor :api_key, :host, :disabled, :logger, :key_file_name
|
8
8
|
|
9
9
|
def initialize
|
10
10
|
@api_key = nil
|
11
11
|
@host = nil
|
12
12
|
@disabled = false
|
13
13
|
@logger = default_logger
|
14
|
+
@key_file_name = nil
|
14
15
|
end
|
15
16
|
|
16
17
|
def disabled?
|
@@ -21,6 +22,10 @@ module Rails
|
|
21
22
|
!api_key.nil? && !api_key.empty?
|
22
23
|
end
|
23
24
|
|
25
|
+
def engine_valid?
|
26
|
+
valid? && !key_file_name.nil? && !key_file_name.empty?
|
27
|
+
end
|
28
|
+
|
24
29
|
private
|
25
30
|
|
26
31
|
def default_logger
|
@@ -5,9 +5,14 @@
|
|
5
5
|
|
6
6
|
Rails::Index::Now.configure do |config|
|
7
7
|
# Required: Your IndexNow API key
|
8
|
-
# You can get one from https://www.
|
8
|
+
# You can get one from https://www.bing.com/indexnow/getstarted
|
9
9
|
config.api_key = ENV.fetch("INDEXNOW_API_KEY", nil)
|
10
10
|
|
11
|
+
# Required: Key file name for IndexNow verification
|
12
|
+
# This should be "YOUR_API_KEY.txt" (replace YOUR_API_KEY with your actual key)
|
13
|
+
# The gem will automatically serve this file at /YOUR_API_KEY.txt
|
14
|
+
config.key_file_name = "#{ENV.fetch("INDEXNOW_API_KEY", "your-api-key")}.txt"
|
15
|
+
|
11
16
|
# Optional: Set a specific host for all submissions
|
12
17
|
# If not set, the gem will extract the host from the submitted URLs
|
13
18
|
# config.host = "example.com"
|
@@ -1,14 +1,26 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "rails/
|
3
|
+
require "rails/engine"
|
4
4
|
|
5
5
|
module Rails
|
6
6
|
module Index
|
7
7
|
module Now
|
8
|
-
class
|
8
|
+
class Engine < ::Rails::Engine
|
9
|
+
isolate_namespace Rails::Index::Now
|
10
|
+
|
9
11
|
generators do
|
10
12
|
require_relative "generators/install_generator"
|
11
13
|
end
|
14
|
+
|
15
|
+
initializer "rails_index_now.add_routes" do |app|
|
16
|
+
app.routes.prepend do
|
17
|
+
config = Rails::Index::Now.configuration
|
18
|
+
if config.engine_valid?
|
19
|
+
get "/#{config.key_file_name}",
|
20
|
+
to: "rails/index/now/verification#index_now_key"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
12
24
|
end
|
13
25
|
end
|
14
26
|
end
|
data/lib/rails/index/now.rb
CHANGED
@@ -4,7 +4,7 @@ require_relative "now/version"
|
|
4
4
|
require_relative "now/configuration"
|
5
5
|
require_relative "now/client"
|
6
6
|
require_relative "now/submit_job" if defined?(ActiveJob::Base)
|
7
|
-
require_relative "now/railtie" if defined?(Rails::
|
7
|
+
require_relative "now/railtie" if defined?(Rails::Engine)
|
8
8
|
|
9
9
|
module Rails
|
10
10
|
module Index
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rails-index-now
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aleks Ulanov
|
@@ -26,6 +26,8 @@ files:
|
|
26
26
|
- LICENSE.txt
|
27
27
|
- README.md
|
28
28
|
- Rakefile
|
29
|
+
- app/controllers/rails/index/now/verification_controller.rb
|
30
|
+
- config/routes.rb
|
29
31
|
- lib/rails/index/now.rb
|
30
32
|
- lib/rails/index/now/client.rb
|
31
33
|
- lib/rails/index/now/configuration.rb
|