Title: WP_Speculation_Rules::add_rule
Published: April 28, 2025

---

# WP_Speculation_Rules::add_rule( string $mode, string $id,  $rule ): bool

## In this article

 * [Parameters](https://developer.wordpress.org/reference/classes/wp_speculation_rules/add_rule/?output_format=md#parameters)
 * [Return](https://developer.wordpress.org/reference/classes/wp_speculation_rules/add_rule/?output_format=md#return)
 * [Source](https://developer.wordpress.org/reference/classes/wp_speculation_rules/add_rule/?output_format=md#source)
 * [Related](https://developer.wordpress.org/reference/classes/wp_speculation_rules/add_rule/?output_format=md#related)
 * [Changelog](https://developer.wordpress.org/reference/classes/wp_speculation_rules/add_rule/?output_format=md#changelog)

[ Back to top](https://developer.wordpress.org/reference/classes/wp_speculation_rules/add_rule/?output_format=md#wp--skip-link--target)

Adds a speculation rule to the speculation rules to consider.

## 󠀁[Parameters](https://developer.wordpress.org/reference/classes/wp_speculation_rules/add_rule/?output_format=md#parameters)󠁿

 `$mode`stringrequired

Speculative loading mode. Either `'prefetch'` or `'prerender'`.

`$id`stringrequired

Unique string identifier for the speculation rule.

mixed> $rule Associative array of rule arguments.

## 󠀁[Return](https://developer.wordpress.org/reference/classes/wp_speculation_rules/add_rule/?output_format=md#return)󠁿

 bool True on success, false if invalid parameters are provided.

## 󠀁[Source](https://developer.wordpress.org/reference/classes/wp_speculation_rules/add_rule/?output_format=md#source)󠁿

    ```php
    public function add_rule( string $mode, string $id, array $rule ): bool {
    	if ( ! self::is_valid_mode( $mode ) ) {
    		_doing_it_wrong(
    			__METHOD__,
    			sprintf(
    				/* translators: %s: invalid mode value */
    				__( 'The value "%s" is not a valid speculation rules mode.' ),
    				esc_html( $mode )
    			),
    			'6.8.0'
    		);
    		return false;
    	}

    	if ( ! $this->is_valid_id( $id ) ) {
    		_doing_it_wrong(
    			__METHOD__,
    			sprintf(
    				/* translators: %s: invalid ID value */
    				__( 'The value "%s" is not a valid ID for a speculation rule.' ),
    				esc_html( $id )
    			),
    			'6.8.0'
    		);
    		return false;
    	}

    	if ( $this->has_rule( $mode, $id ) ) {
    		_doing_it_wrong(
    			__METHOD__,
    			sprintf(
    				/* translators: %s: invalid ID value */
    				__( 'A speculation rule with ID "%s" already exists.' ),
    				esc_html( $id )
    			),
    			'6.8.0'
    		);
    		return false;
    	}

    	/*
    	 * Perform some basic speculation rule validation.
    	 * Every rule must have either a 'where' key or a 'urls' key, but not both.
    	 * The presence of a 'where' key implies a 'source' of 'document', while the presence of a 'urls' key implies
    	 * a 'source' of 'list'.
    	 */
    	if (
    		( ! isset( $rule['where'] ) && ! isset( $rule['urls'] ) ) ||
    		( isset( $rule['where'] ) && isset( $rule['urls'] ) )
    	) {
    		_doing_it_wrong(
    			__METHOD__,
    			sprintf(
    				/* translators: 1: allowed key, 2: alternative allowed key */
    				__( 'A speculation rule must include either a "%1$s" key or a "%2$s" key, but not both.' ),
    				'where',
    				'urls'
    			),
    			'6.8.0'
    		);
    		return false;
    	}
    	if ( isset( $rule['source'] ) ) {
    		if ( ! self::is_valid_source( $rule['source'] ) ) {
    			_doing_it_wrong(
    				__METHOD__,
    				sprintf(
    					/* translators: %s: invalid source value */
    					__( 'The value "%s" is not a valid source for a speculation rule.' ),
    					esc_html( $rule['source'] )
    				),
    				'6.8.0'
    			);
    			return false;
    		}

    		if ( 'list' === $rule['source'] && isset( $rule['where'] ) ) {
    			_doing_it_wrong(
    				__METHOD__,
    				sprintf(
    					/* translators: 1: source value, 2: forbidden key */
    					__( 'A speculation rule of source "%1$s" must not include a "%2$s" key.' ),
    					'list',
    					'where'
    				),
    				'6.8.0'
    			);
    			return false;
    		}

    		if ( 'document' === $rule['source'] && isset( $rule['urls'] ) ) {
    			_doing_it_wrong(
    				__METHOD__,
    				sprintf(
    					/* translators: 1: source value, 2: forbidden key */
    					__( 'A speculation rule of source "%1$s" must not include a "%2$s" key.' ),
    					'document',
    					'urls'
    				),
    				'6.8.0'
    			);
    			return false;
    		}
    	}

    	// If there is an 'eagerness' key specified, make sure it's valid.
    	if ( isset( $rule['eagerness'] ) ) {
    		if ( ! self::is_valid_eagerness( $rule['eagerness'] ) ) {
    			_doing_it_wrong(
    				__METHOD__,
    				sprintf(
    					/* translators: %s: invalid eagerness value */
    					__( 'The value "%s" is not a valid eagerness for a speculation rule.' ),
    					esc_html( $rule['eagerness'] )
    				),
    				'6.8.0'
    			);
    			return false;
    		}

    		if ( isset( $rule['where'] ) && 'immediate' === $rule['eagerness'] ) {
    			_doing_it_wrong(
    				__METHOD__,
    				sprintf(
    					/* translators: %s: forbidden eagerness value */
    					__( 'The eagerness value "%s" is forbidden for document-level speculation rules.' ),
    					'immediate'
    				),
    				'6.8.0'
    			);
    			return false;
    		}
    	}

    	if ( ! isset( $this->rules_by_mode[ $mode ] ) ) {
    		$this->rules_by_mode[ $mode ] = array();
    	}

    	$this->rules_by_mode[ $mode ][ $id ] = $rule;
    	return true;
    }
    ```

[View all references](https://developer.wordpress.org/reference/files/wp-includes/class-wp-speculation-rules.php/)
[View on Trac](https://core.trac.wordpress.org/browser/tags/6.9.4/src/wp-includes/class-wp-speculation-rules.php#L73)
[View on GitHub](https://github.com/WordPress/wordpress-develop/blob/6.9.4/src/wp-includes/class-wp-speculation-rules.php#L73-L213)

## 󠀁[Related](https://developer.wordpress.org/reference/classes/wp_speculation_rules/add_rule/?output_format=md#related)󠁿

| Uses | Description | 
| [WP_Speculation_Rules::is_valid_mode()](https://developer.wordpress.org/reference/classes/wp_speculation_rules/is_valid_mode/)`wp-includes/class-wp-speculation-rules.php` |

Checks whether the given speculation rules mode is valid.

  | 
| [WP_Speculation_Rules::is_valid_id()](https://developer.wordpress.org/reference/classes/wp_speculation_rules/is_valid_id/)`wp-includes/class-wp-speculation-rules.php` |

Checks whether the given ID is valid.

  | 
| [WP_Speculation_Rules::is_valid_source()](https://developer.wordpress.org/reference/classes/wp_speculation_rules/is_valid_source/)`wp-includes/class-wp-speculation-rules.php` |

Checks whether the given speculation rules source is valid.

  | 
| [WP_Speculation_Rules::is_valid_eagerness()](https://developer.wordpress.org/reference/classes/wp_speculation_rules/is_valid_eagerness/)`wp-includes/class-wp-speculation-rules.php` |

Checks whether the given speculation rules eagerness is valid.

  | 
| [WP_Speculation_Rules::has_rule()](https://developer.wordpress.org/reference/classes/wp_speculation_rules/has_rule/)`wp-includes/class-wp-speculation-rules.php` |

Checks whether a speculation rule for the given mode and ID already exists.

  | 
| [__()](https://developer.wordpress.org/reference/functions/__/)`wp-includes/l10n.php` |

Retrieves the translation of $text.

  | 
| [esc_html()](https://developer.wordpress.org/reference/functions/esc_html/)`wp-includes/formatting.php` |

Escaping for HTML blocks.

  | 
| [_doing_it_wrong()](https://developer.wordpress.org/reference/functions/_doing_it_wrong/)`wp-includes/functions.php` |

Marks something as being incorrectly called.

  |

[Show 3 more](https://developer.wordpress.org/reference/classes/wp_speculation_rules/add_rule/?output_format=md#)
[Show less](https://developer.wordpress.org/reference/classes/wp_speculation_rules/add_rule/?output_format=md#)

## 󠀁[Changelog](https://developer.wordpress.org/reference/classes/wp_speculation_rules/add_rule/?output_format=md#changelog)󠁿

| Version | Description | 
| [6.8.0](https://developer.wordpress.org/reference/since/6.8.0/) | Introduced. |

## User Contributed Notes

You must [log in](https://login.wordpress.org/?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Fclasses%2Fwp_speculation_rules%2Fadd_rule%2F)
before being able to contribute a note or feedback.