v1.0.0
This commit is contained in:
parent
ac2c7a8014
commit
f7702f2872
25 changed files with 6453 additions and 0 deletions
240
docs/FILTERS-HOOKS.md
Normal file
240
docs/FILTERS-HOOKS.md
Normal file
|
|
@ -0,0 +1,240 @@
|
|||
# Filters & Hooks Reference
|
||||
|
||||
Developer reference for all filters and actions provided by the **OpenGraph (by ROBOTSTXT)** plugin.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Filters](#filters)
|
||||
- [robotstxt_og_external_image_enabled](#robotstxt_og_external_image_enabled)
|
||||
- [robotstxt_og_external_image_timeout](#robotstxt_og_external_image_timeout)
|
||||
- [robotstxt_og_taxonomy_image](#robotstxt_og_taxonomy_image)
|
||||
- [robotstxt_og_enable_logging](#robotstxt_og_enable_logging)
|
||||
- [Actions](#actions)
|
||||
- [SEO Plugin Integrations](#seo-plugin-integrations)
|
||||
|
||||
---
|
||||
|
||||
## Filters
|
||||
|
||||
### `robotstxt_og_external_image_enabled`
|
||||
|
||||
Controls whether the plugin attempts to resolve fallback images for external URLs (images hosted on a different domain than the WordPress site).
|
||||
|
||||
**Default:** `true`
|
||||
|
||||
**Parameters:**
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|------|-------------|
|
||||
| `$enabled` | `bool` | Whether external image resolution is enabled. |
|
||||
| `$image_url` | `string` | The external image URL being evaluated. |
|
||||
|
||||
**Returns:** `bool`
|
||||
|
||||
**Example — disable external image resolution entirely:**
|
||||
|
||||
```php
|
||||
add_filter( 'robotstxt_og_external_image_enabled', '__return_false' );
|
||||
```
|
||||
|
||||
**Example — disable only for a specific CDN domain:**
|
||||
|
||||
```php
|
||||
add_filter( 'robotstxt_og_external_image_enabled', function ( bool $enabled, string $image_url ): bool {
|
||||
if ( str_contains( $image_url, 'cdn.example.com' ) ) {
|
||||
return false;
|
||||
}
|
||||
return $enabled;
|
||||
}, 10, 2 );
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `robotstxt_og_external_image_timeout`
|
||||
|
||||
Sets the HTTP request timeout (in seconds) used when verifying whether a fallback image URL exists via a HEAD request.
|
||||
|
||||
**Default:** `5` (seconds)
|
||||
|
||||
**Parameters:**
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|------|-------------|
|
||||
| `$timeout` | `int` | Timeout in seconds for the HEAD request. |
|
||||
| `$url` | `string` | The image URL being tested. |
|
||||
|
||||
**Returns:** `int`
|
||||
|
||||
**Example — increase timeout for slow external servers:**
|
||||
|
||||
```php
|
||||
add_filter( 'robotstxt_og_external_image_timeout', function ( int $timeout, string $url ): int {
|
||||
if ( str_contains( $url, 'slow-cdn.example.com' ) ) {
|
||||
return 15;
|
||||
}
|
||||
return $timeout;
|
||||
}, 10, 2 );
|
||||
```
|
||||
|
||||
**Example — set a global lower timeout for performance:**
|
||||
|
||||
```php
|
||||
add_filter( 'robotstxt_og_external_image_timeout', function (): int {
|
||||
return 3;
|
||||
} );
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `robotstxt_og_taxonomy_image`
|
||||
|
||||
Provides a fallback OG image URL for taxonomy archive pages (categories, tags, custom taxonomies). By default, taxonomy archives do not have a featured image, so this filter is the primary way to supply one.
|
||||
|
||||
**Default:** `''` (empty string — no image)
|
||||
|
||||
**Parameters:**
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|------|-------------|
|
||||
| `$image_url` | `string` | Image URL to use. Empty string by default. |
|
||||
| `$term_id` | `int` | The term ID of the current taxonomy archive. |
|
||||
|
||||
**Returns:** `string` A valid image URL, or empty string to skip.
|
||||
|
||||
**Example — use a custom field set on the term:**
|
||||
|
||||
```php
|
||||
add_filter( 'robotstxt_og_taxonomy_image', function ( string $image_url, int $term_id ): string {
|
||||
$custom_image_id = get_term_meta( $term_id, 'og_image_id', true );
|
||||
|
||||
if ( $custom_image_id ) {
|
||||
$url = wp_get_attachment_url( (int) $custom_image_id );
|
||||
return $url ? $url : $image_url;
|
||||
}
|
||||
|
||||
return $image_url;
|
||||
}, 10, 2 );
|
||||
```
|
||||
|
||||
**Example — use a WooCommerce category thumbnail:**
|
||||
|
||||
```php
|
||||
add_filter( 'robotstxt_og_taxonomy_image', function ( string $image_url, int $term_id ): string {
|
||||
$thumbnail_id = get_term_meta( $term_id, 'thumbnail_id', true );
|
||||
|
||||
if ( $thumbnail_id ) {
|
||||
$url = wp_get_attachment_url( (int) $thumbnail_id );
|
||||
return $url ? $url : $image_url;
|
||||
}
|
||||
|
||||
return $image_url;
|
||||
}, 10, 2 );
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `robotstxt_og_enable_logging`
|
||||
|
||||
Enables or disables debug logging to `wp-content/debug.log`. When enabled, resolution events (cache hits, cache misses, format detection, HEAD request results) are written to the error log.
|
||||
|
||||
**Default:** `false`
|
||||
|
||||
**Parameters:**
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|------|-------------|
|
||||
| `$enabled` | `bool` | Whether debug logging is active. |
|
||||
|
||||
**Returns:** `bool`
|
||||
|
||||
**Note:** Requires `WP_DEBUG` and `WP_DEBUG_LOG` to be enabled in `wp-config.php` for output to appear in `debug.log`.
|
||||
|
||||
**Example — enable logging (e.g. during development, in `wp-config.php`):**
|
||||
|
||||
```php
|
||||
// wp-config.php
|
||||
define( 'WP_DEBUG', true );
|
||||
define( 'WP_DEBUG_LOG', true );
|
||||
```
|
||||
|
||||
```php
|
||||
// functions.php or a mu-plugin
|
||||
add_filter( 'robotstxt_og_enable_logging', '__return_true' );
|
||||
```
|
||||
|
||||
**Example — enable logging only for specific users:**
|
||||
|
||||
```php
|
||||
add_filter( 'robotstxt_og_enable_logging', function ( bool $enabled ): bool {
|
||||
return current_user_can( 'manage_options' ) ? true : $enabled;
|
||||
} );
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Actions
|
||||
|
||||
The plugin does not currently expose custom action hooks. WordPress core hooks used internally include:
|
||||
|
||||
| Hook | Context | Purpose |
|
||||
|------|---------|---------|
|
||||
| `plugins_loaded` | Global | Loads text domain for translations. |
|
||||
| `wp_head` | Frontend | Injects `og:image` meta tags (only when no SEO plugin is active). |
|
||||
| `admin_menu` | Admin | Registers the Settings > OpenGraph settings page. |
|
||||
| `admin_init` | Admin | Registers settings, handles cache clear/resolve actions. |
|
||||
| `admin_enqueue_scripts` | Admin | Enqueues media uploader and admin CSS/JS. |
|
||||
| `rest_api_init` | REST API | Registers the `robotstxt-og/v1` REST endpoints. |
|
||||
| `updated_post_meta` | Global | Auto-clears fallback cache when `_thumbnail_id` changes. |
|
||||
| `deleted_post_meta` | Global | Auto-clears fallback cache when `_thumbnail_id` is removed. |
|
||||
|
||||
---
|
||||
|
||||
## SEO Plugin Integrations
|
||||
|
||||
When a supported SEO plugin is detected, the plugin switches from direct `og:image` tag injection to filtering the SEO plugin's output. This prevents duplicate meta tags.
|
||||
|
||||
### Yoast SEO
|
||||
|
||||
**Filter:** `wpseo_opengraph_image`
|
||||
|
||||
When Yoast SEO is active (`WPSEO_VERSION` is defined), the plugin hooks into this filter to provide the resolved fallback image. The plugin only overrides the value if a valid fallback URL is resolved; otherwise it returns the original Yoast value unchanged.
|
||||
|
||||
### RankMath
|
||||
|
||||
**Filter:** `rank_math/opengraph/facebook/og_image`
|
||||
|
||||
When RankMath is active (`RankMath` class exists), the plugin hooks into this filter with the same logic as the Yoast integration.
|
||||
|
||||
### Adding Support for Other SEO Plugins
|
||||
|
||||
To integrate with another SEO plugin, hook into the plugin's OG image filter and call the resolver manually:
|
||||
|
||||
```php
|
||||
add_filter( 'your_seo_plugin_og_image_filter', function ( string $image ) : string {
|
||||
if ( ! is_singular() ) {
|
||||
return $image;
|
||||
}
|
||||
|
||||
$post_id = get_queried_object_id();
|
||||
$resolver = Robotstxt_OG_Image_Fallback::get_instance()->get_resolver();
|
||||
$fallback = $resolver->get_fallback_image( $post_id );
|
||||
|
||||
return ! empty( $fallback ) ? $fallback : $image;
|
||||
} );
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Postmeta Keys (Internal Cache)
|
||||
|
||||
These postmeta keys are used internally for caching and should not be modified directly:
|
||||
|
||||
| Meta Key | Type | Description |
|
||||
|----------|------|-------------|
|
||||
| `_og_image_fallback_url` | `string` | Cached resolved fallback image URL for a post. |
|
||||
|
||||
These transient keys are used for negative caching (failed HEAD request results):
|
||||
|
||||
| Transient Key Pattern | TTL | Description |
|
||||
|-----------------------|-----|-------------|
|
||||
| `robotstxt_og_miss_{md5_of_url}` | 1 hour | Marks a URL as unreachable to prevent repeated requests. |
|
||||
183
docs/OG-TWITTER-REFERENCE.md
Normal file
183
docs/OG-TWITTER-REFERENCE.md
Normal file
|
|
@ -0,0 +1,183 @@
|
|||
# Open Graph & Twitter Cards — Reference
|
||||
|
||||
This document covers the Open Graph (OG) and Twitter Cards meta tag specifications relevant to this plugin, including which tags are mandatory, recommended, optional, and which this plugin outputs automatically.
|
||||
|
||||
---
|
||||
|
||||
## Open Graph Protocol
|
||||
|
||||
Defined by Facebook/Meta. All OG tags use the `property` attribute.
|
||||
|
||||
### Core Tags (og: namespace)
|
||||
|
||||
| Property | Type | Required | Notes |
|
||||
|---|---|---|---|
|
||||
| `og:title` | string | **Required** | Title of the content. Used by all social crawlers. |
|
||||
| `og:type` | string | **Required** | Content type: `website`, `article`, `video.movie`, etc. |
|
||||
| `og:url` | URL | **Required** | Canonical URL of the page. |
|
||||
| `og:description` | string | Recommended | Short description (2–4 sentences). Max ~300 chars. |
|
||||
| `og:site_name` | string | Recommended | Name of the overall site (e.g. "My Blog"). |
|
||||
| `og:locale` | string | Recommended | Locale in `language_TERRITORY` format (e.g. `es_ES`). |
|
||||
| `og:image` | URL | **Required** (for cards) | Must be JPEG or PNG for social crawler compatibility. Min 200×200 px. Recommended 1200×630 px. |
|
||||
| `og:image:secure_url` | URL | Optional | HTTPS version of `og:image`. Same value when the site is HTTPS-only. |
|
||||
| `og:image:type` | MIME type | Recommended | MIME type of the image (`image/jpeg`, `image/png`). |
|
||||
| `og:image:width` | integer | Recommended | Width in pixels. Avoids reflow in crawler previews. |
|
||||
| `og:image:height` | integer | Recommended | Height in pixels. |
|
||||
| `og:image:alt` | string | Recommended | Alt text for the image. Required for accessibility audits. |
|
||||
|
||||
### Article Tags (article: namespace)
|
||||
|
||||
Used when `og:type = article`. All are optional but recommended for news/blog content.
|
||||
|
||||
| Property | Type | Notes |
|
||||
|---|---|---|
|
||||
| `article:published_time` | ISO 8601 datetime | Publication date (`c` format in PHP: `get_the_date('c')`). |
|
||||
| `article:modified_time` | ISO 8601 datetime | Last modification date. |
|
||||
| `article:author` | URL | Profile page of the author (Facebook profile URL). Often omitted. |
|
||||
| `article:section` | string | Primary category or section (e.g. "Technology"). |
|
||||
| `article:tag` | string | Topic tags. Can be repeated once per tag. |
|
||||
| `article:expiration_time` | ISO 8601 datetime | When the article expires (rarely used). |
|
||||
|
||||
### Video Tags (video: namespace)
|
||||
|
||||
For `og:type = video.movie`, `video.episode`, etc. Out of scope for this plugin.
|
||||
|
||||
---
|
||||
|
||||
## Twitter Cards
|
||||
|
||||
Defined by X (formerly Twitter). Tags use the `name` attribute (not `property`).
|
||||
|
||||
Twitter falls back to `og:*` tags if the corresponding `twitter:*` tag is absent — **except** `twitter:card`, which is always required.
|
||||
|
||||
### Card Types
|
||||
|
||||
| Value | Description |
|
||||
|---|---|
|
||||
| `summary` | Small square image (minimum 144×144 px). |
|
||||
| `summary_large_image` | Large rectangular image (minimum 300×157 px, recommended 1200×628 px). Most common for blog/news content. |
|
||||
| `app` | Promotes a mobile app. |
|
||||
| `player` | Embeds a video/audio player. |
|
||||
|
||||
### Twitter Tags
|
||||
|
||||
| Name | Required | Falls back to | Notes |
|
||||
|---|---|---|---|
|
||||
| `twitter:card` | **Required** | — | Must always be present. Without it, no Twitter Card is shown. |
|
||||
| `twitter:site` | Recommended | — | `@username` of the site's Twitter/X account. |
|
||||
| `twitter:creator` | Optional | — | `@username` of the content author. |
|
||||
| `twitter:title` | Recommended | `og:title` | Title of the content. |
|
||||
| `twitter:description` | Recommended | `og:description` | Description. Max 200 chars. |
|
||||
| `twitter:image` | Recommended | `og:image` | Must be JPEG, PNG, WebP, or GIF. Max 5 MB. |
|
||||
| `twitter:image:alt` | Recommended | `og:image:alt` | Alt text for the image. Max 420 chars. |
|
||||
|
||||
---
|
||||
|
||||
## What This Plugin Outputs
|
||||
|
||||
### When no SEO plugin is active (direct injection)
|
||||
|
||||
The plugin outputs a **complete** set of OG and Twitter Card tags via `wp_head` (priority 5).
|
||||
|
||||
#### Open Graph tags
|
||||
|
||||
```html
|
||||
<!-- Core -->
|
||||
<meta property="og:title" content="..." />
|
||||
<meta property="og:type" content="article" /> <!-- or "website" -->
|
||||
<meta property="og:url" content="..." />
|
||||
<meta property="og:description" content="..." /> <!-- when available -->
|
||||
<meta property="og:site_name" content="..." />
|
||||
<meta property="og:locale" content="es_ES" />
|
||||
|
||||
<!-- Image (when a compatible image is resolved) -->
|
||||
<meta property="og:image" content="https://...jpg" />
|
||||
<meta property="og:image:secure_url" content="https://...jpg" /> <!-- HTTPS only -->
|
||||
<meta property="og:image:width" content="1200" />
|
||||
<meta property="og:image:height" content="630" />
|
||||
<meta property="og:image:type" content="image/jpeg" />
|
||||
<meta property="og:image:alt" content="..." /> <!-- when set in media library -->
|
||||
|
||||
<!-- Article-specific (og:type = article only) -->
|
||||
<meta property="article:published_time" content="2026-02-18T00:00:00+00:00" />
|
||||
<meta property="article:modified_time" content="2026-02-18T00:00:00+00:00" />
|
||||
<meta property="article:section" content="Technology" /> <!-- primary category -->
|
||||
<meta property="article:tag" content="WordPress" /> <!-- repeated per tag -->
|
||||
```
|
||||
|
||||
#### Twitter Card tags
|
||||
|
||||
```html
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
<meta name="twitter:site" content="@example" /> <!-- when configured in Settings -->
|
||||
<meta name="twitter:image" content="https://...jpg" /> <!-- when image available -->
|
||||
```
|
||||
|
||||
> Twitter falls back to `og:title`, `og:description`, and `og:image` automatically, so those tags are not duplicated.
|
||||
|
||||
### When Yoast SEO or RankMath is active
|
||||
|
||||
The plugin acts as a **corrector only**: it filters the image URL via the SEO plugin's filter hook, converting incompatible formats (AVIF/WebP) to JPEG/PNG. All other OG/Twitter tags are managed by the SEO plugin.
|
||||
|
||||
---
|
||||
|
||||
## og:type Values Reference
|
||||
|
||||
| Value | When to use |
|
||||
|---|---|
|
||||
| `website` | Default for homepages and most pages. |
|
||||
| `article` | Blog posts, news articles. This plugin uses this for `is_singular('post')`. |
|
||||
| `profile` | User profile pages. |
|
||||
| `video.movie` | Movie pages. |
|
||||
| `video.episode` | TV episode pages. |
|
||||
| `music.song` | Song pages. |
|
||||
| `music.album` | Album pages. |
|
||||
|
||||
---
|
||||
|
||||
## Per-Post Overrides (Editor Meta Box)
|
||||
|
||||
The plugin adds an **"Open Graph / Social Media"** meta box to all post editors, allowing per-post overrides of:
|
||||
|
||||
| Field | OG Tag | Fallback |
|
||||
|---|---|---|
|
||||
| Custom Title | `og:title` | Post title (`get_the_title()`) |
|
||||
| Custom Description | `og:description` | Post excerpt, or empty |
|
||||
|
||||
These overrides are stored as post meta:
|
||||
- `_og_title` — custom OG title
|
||||
- `_og_description` — custom OG description
|
||||
|
||||
---
|
||||
|
||||
## Context → og:type Mapping (this plugin)
|
||||
|
||||
| WordPress context | `og:type` |
|
||||
|---|---|
|
||||
| `is_singular('post')` | `article` |
|
||||
| `is_singular('page')` | `website` |
|
||||
| `is_singular(other)` | `website` |
|
||||
| `is_front_page()` / `is_home()` | `website` |
|
||||
| `is_tax()` / `is_category()` / `is_tag()` | `website` |
|
||||
|
||||
---
|
||||
|
||||
## Image Compatibility
|
||||
|
||||
Social crawlers (Facebook, X, LinkedIn, WhatsApp, Telegram) generally require:
|
||||
- Format: **JPEG or PNG** (WebP partial support; AVIF not supported)
|
||||
- Minimum size: 200×200 px (Facebook requires 200×200 for `summary`)
|
||||
- Recommended: 1200×630 px for `summary_large_image`
|
||||
- Max file size: 8 MB (Facebook), 5 MB (Twitter)
|
||||
|
||||
This plugin's core function is to detect when a featured image is in an incompatible format (AVIF, WebP) and automatically serve a JPEG/PNG alternative via fallback resolution.
|
||||
|
||||
---
|
||||
|
||||
## Validation Tools
|
||||
|
||||
- **Facebook**: [Sharing Debugger](https://developers.facebook.com/tools/debug/)
|
||||
- **Twitter/X**: [Card Validator](https://cards-dev.twitter.com/validator)
|
||||
- **LinkedIn**: [Post Inspector](https://www.linkedin.com/post-inspector/)
|
||||
- **OpenGraph.xyz**: [OpenGraph preview](https://www.opengraph.xyz/)
|
||||
- **Metatags.io**: [Meta tag preview](https://metatags.io/)
|
||||
103
docs/WP-CLI.md
Normal file
103
docs/WP-CLI.md
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
# WP-CLI Command Reference
|
||||
|
||||
The plugin registers WP-CLI commands under the `og-fallback` namespace.
|
||||
|
||||
## Commands
|
||||
|
||||
### `wp og-fallback resolve`
|
||||
|
||||
Resolves (or re-resolves) the OG fallback image for one or all posts with featured images.
|
||||
|
||||
**Usage:**
|
||||
|
||||
```bash
|
||||
wp og-fallback resolve [<post_id>] [--all] [--dry-run] [--post-type=<type>]
|
||||
```
|
||||
|
||||
**Arguments:**
|
||||
|
||||
| Argument | Description |
|
||||
|----------|-------------|
|
||||
| `<post_id>` | (optional) Single post ID to resolve. |
|
||||
| `--all` | Process all posts that have a featured image. |
|
||||
| `--dry-run` | Preview without making any changes. |
|
||||
| `--post-type=<type>` | Limit `--all` to a specific post type (default: `any`). |
|
||||
|
||||
**Examples:**
|
||||
|
||||
```bash
|
||||
# Resolve fallback for a single post
|
||||
wp og-fallback resolve 123
|
||||
|
||||
# Preview for a single post without saving
|
||||
wp og-fallback resolve 123 --dry-run
|
||||
|
||||
# Re-resolve all posts (clears cache first)
|
||||
wp og-fallback resolve --all
|
||||
|
||||
# Re-resolve only 'product' post type posts
|
||||
wp og-fallback resolve --all --post-type=product
|
||||
|
||||
# Dry-run all (shows count, no changes)
|
||||
wp og-fallback resolve --all --dry-run
|
||||
```
|
||||
|
||||
**Output examples:**
|
||||
|
||||
```
|
||||
Success: Post 123 resolved to https://example.com/uploads/image.jpg
|
||||
Warning: Post 456: no compatible image found.
|
||||
Success: Resolved 47 posts. Failed: 2.
|
||||
Found 49 posts with featured images. (dry-run, no changes made)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `wp og-fallback clear-cache`
|
||||
|
||||
Deletes cached fallback URLs from postmeta.
|
||||
|
||||
**Usage:**
|
||||
|
||||
```bash
|
||||
wp og-fallback clear-cache [<post_id>] [--all] [--dry-run]
|
||||
```
|
||||
|
||||
**Arguments:**
|
||||
|
||||
| Argument | Description |
|
||||
|----------|-------------|
|
||||
| `<post_id>` | (optional) Single post ID to clear cache for. |
|
||||
| `--all` | Clear all cached fallback URLs. |
|
||||
| `--dry-run` | Preview without making any changes. |
|
||||
|
||||
**Examples:**
|
||||
|
||||
```bash
|
||||
# Clear cache for a single post
|
||||
wp og-fallback clear-cache 123
|
||||
|
||||
# Clear all cached fallback URLs
|
||||
wp og-fallback clear-cache --all
|
||||
|
||||
# Preview how many entries would be cleared
|
||||
wp og-fallback clear-cache --all --dry-run
|
||||
```
|
||||
|
||||
**Output examples:**
|
||||
|
||||
```
|
||||
Success: Cleared cached fallback URL for post 123.
|
||||
Warning: Post 456 has no cached fallback URL.
|
||||
Success: Cleared 47 cached fallback URLs.
|
||||
Found 47 cached fallback URLs. (dry-run, no changes made)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Notes
|
||||
|
||||
- Both commands require WP-CLI 2.x.
|
||||
- No capability check is enforced at the CLI level (WP-CLI access implies server-level trust).
|
||||
- The `--all` flag with `resolve` is equivalent to clicking **Re-resolve All Images** in the admin Tools tab.
|
||||
- The `--all` flag with `clear-cache` is equivalent to clicking **Clear All Cached URLs** in the admin Tools tab.
|
||||
Loading…
Reference in a new issue