Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions plugins/optimization-detective/docs/extensions.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ For development and debugging, also on GitHub:

* [Optimization Detective Admin UI](https://github.com/westonruter/od-admin-ui): Provides an admin UI to inspect URL Metrics from the Optimization Detective plugin.
* [Optimization Detective Debug Helper](https://github.com/swissspidy/od-debug-helper/): Makes data from Optimization Detective visible on the front end through the admin bar.
* [Optimization Detective Default Disabled](https://gist.github.com/westonruter/9e9036e8dc11292279a90995273c7adc): Disables Optimization Detective by default unless you supply the `?optimization_detective_enabled=1` query parameter to the URL. This allows you to debug issues on a live site without visitors seeing a broken experience.
* [Optimization Detective Store Query Vars](https://github.com/westonruter/od-store-query-vars): Stores the Query Vars with a URL Metric in the Optimization Detective plugin. This is useful for debugging URL Metrics, in particular what the slug was computed from.
* [Optimization Detective Store User Agent](https://github.com/westonruter/od-store-user-agent): Stores the User Agent with a URL Metric in the Optimization Detective plugin. This is useful for debugging URL Metrics, in particular to understand what device has a given viewport dimensions.
* [Optimization Detective Dev Mode](https://github.com/westonruter/od-dev-mode): Adds filters to facilitate development of the Optimization Detective plugin.
26 changes: 24 additions & 2 deletions plugins/optimization-detective/docs/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,12 @@ After a URL Metric has been submitted to the REST API storage endpoint and is va
| `post_content` | A JSON array of all the URL Metric objects. |
| `post_title` | The `url` property of the most recent URL Metric stored in the post. (This is useful when listing out posts with WP-CLI.) |

When an `od_url_metrics` post has not been updated in a month then it is garbage-collected, since it is likely the original URL has gone away.

Extensions to Optimization Detective rarely need to directly interface with the custom post type, so far. See the experimental [Optimization Detective Content Visibility](https://github.com/westonruter/od-content-visibility/) plugin which interfaces with the `od_url_metrics` post at submission time to add post meta via the `od_url_metric_stored` action, and then retrieves post meta in the tag visitor via the context object’s `url_metrics_id` property.

## Varying URL Metrics for Dynamic Responses

The slug (`post_name`) of the post is derived from the public WP query vars (`$wp->query_vars`) since site traffic may often request URLs that contain arbitrary query parameters that have no impact on the rendered page (e.g. UTM parameters). So using these WP query vars ensures that such insignificant URL variations are normalized. If there are URL Metrics for separate distinct URLs being stored in the same `od_url_metrics` post unexpectedly, it may be due to a significant GET query parameter not being registered among the public query vars via the `query_vars` filter. For example, if you have a contact form which redirects back to itself with a `?thank_you=1` in the URL to show a "thank you" message instead of the submission form, and this template contains the following:

```php
Expand All @@ -186,9 +192,25 @@ add_filter( 'query_vars', function ( $query_vars ) {

Then in your template code you may continue to use `isset( $_GET['thank_you'] )` but you might as well use `get_query_var( 'thank_you' )` instead.

When an `od_url_metrics` post has not been updated in a month then it is garbage-collected, since it is likely the original URL has gone away.
This is also important if you are serving different pages for mobile versus desktop (i.e. not responsive web design but adaptive web design). For this you'll want to populate the query vars with whether it is a mobile request:

Extensions to Optimization Detective rarely need to directly interface with the custom post type, so far. See the experimental [Optimization Detective Content Visibility](https://github.com/westonruter/od-content-visibility/) plugin which interfaces with the `od_url_metrics` post at submission time to add post meta via the `od_url_metric_stored` action, and then retrieves post meta in the tag visitor via the context object’s `url_metrics_id` property.
```php
add_action( 'wp', function ( WP $wp ) {
if ( wp_is_mobile() ) {
$wp->add_query_var( 'is_mobile', true );
}
} );
```

The same goes for sites that serve different pages content based on geolocation, for example if you serve different content specifically to North America:

```php
add_action( 'wp', function ( WP $wp ) {
if ( in_array( Geo\get_geo( 'country-code' ), array( 'CA', 'US', 'MX' ) ) ) {
$wp->add_query_var( 'is_north_america', true );
}
} );
```

# Conditional Optimization

Expand Down
22 changes: 16 additions & 6 deletions plugins/optimization-detective/storage/data.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,25 @@
function od_get_normalized_query_vars(): array {
global $wp;

// Note that the order of this array is naturally normalized since it is
// assembled by iterating over public_query_vars.
$normalized_query_vars = $wp->query_vars;

// Normalize unbounded query vars.
if ( is_404() ) {
// Note that 404 responses are not optimized by default, but they can be forcibly made to be optimized via
// the od_can_optimize_response filter. Since any query vars in a 404 response by definition do not correspond
// to any valid content on the site, all the query vars should be overridden to indicate the 404 state.
$normalized_query_vars = array(
'error' => 404,
);
} else {
$normalized_query_vars = $wp->query_vars;

// Note that search responses are not optimized by default, but they can be forcibly made to be optimized via
// the od_can_optimize_response filter. Since by definition there are no constraints on what can be searched for
// the 's' query var must be normalized to prevent an unbounded URL space.
if ( isset( $normalized_query_vars['s'] ) ) {
$normalized_query_vars['s'] = '';

Check warning on line 66 in plugins/optimization-detective/storage/data.php

View check run for this annotation

Codecov / codecov/patch

plugins/optimization-detective/storage/data.php#L66

Added line #L66 was not covered by tests
}

// Re-sorted to account for query vars added via $wp->set_query_var().
ksort( $normalized_query_vars );
}

return $normalized_query_vars;
Expand Down Expand Up @@ -117,7 +127,7 @@
* @return non-empty-string Slug.
*/
function od_get_url_metrics_slug( array $query_vars ): string {
return md5( (string) wp_json_encode( $query_vars ) );
return md5( (string) wp_json_encode( $query_vars, JSON_FORCE_OBJECT ) );
}

/**
Expand Down
4 changes: 2 additions & 2 deletions plugins/optimization-detective/tests/storage/test-data.php
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,9 @@ public function data_provider_test_od_get_normalized_query_vars(): array {
)
);
return array(
'year' => $date->format( 'Y' ),
'monthnum' => $date->format( 'm' ),
'day' => $date->format( 'j' ),
'monthnum' => $date->format( 'm' ),
'year' => $date->format( 'Y' ),
);
},
),
Expand Down