Skip to content

Commit

Permalink
Seo canonical optimization (#196)
Browse files Browse the repository at this point in the history
* added get canonical term link functions for supported third-party SEO plugins

* added support portfolio taxonomy canonical for Yoast plugin

* added support portfolio taxonomy canonical for Rank Math plugin

* added support portfolio taxonomy canonical for All In One Seo plugin

* improved get term link function: added query argument for supported execute on other places

* added a comment on the use of the custom category tag for a better understanding of the code

* added support graph schema for Yoast 3rd plugin

* added support Yoast graph schema for webpage, breadcrumb and potential action target

* added new get canonical and get canonical anchor functions for optimize and get canonical anchor url

* refactored and simplify Yoast class

* added title filters to Rank Math and refactored this class

* added support graph scheme for All In One Seo and refactored canonical filter

* fixed graph fatal error for Yoast plugin support

* fixed All In One Seo errors and added temporary query functions for plugin works

* fixed Rank Math errors and added temporary query functions for plugin works

* added is category function for check portfolio category

* added convert category url on portfolio item to friendly view and refactored code of parsing category url
  • Loading branch information
Fellan-91 authored Nov 25, 2023
1 parent 683e02e commit e7f6b13
Show file tree
Hide file tree
Showing 4 changed files with 362 additions and 75 deletions.
86 changes: 75 additions & 11 deletions classes/3rd/plugins/class-all-in-one-seo.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,88 @@ class Visual_Portfolio_3rd_All_In_One_Seo {
*/
public function __construct() {
// Fixed canonical links.
add_filter( 'aioseo_canonical_url', array( $this, 'canonical' ) );
add_filter( 'aioseo_canonical_url', array( 'Visual_Portfolio_Archive_Mapping', 'get_canonical' ) );
add_filter( 'aioseo_schema_output', array( $this, 'graph_schema_output' ) );
add_action( 'wp_print_footer_scripts', array( $this, 'set_query_as_archive' ), 8 ); // priority one level lower than what the plugin uses.
add_action( 'wp_print_footer_scripts', array( $this, 'remove_query_as_archive' ), 13 ); // priority one level higher than what the plugin uses.
add_action( 'wp', array( $this, 'set_query_as_archive' ), 9 );
add_action( 'wp', array( $this, 'remove_query_as_archive' ), 13 );
}

/**
* Optimize url by supported GET variables: vp_page, vp_filter, vp_sort and vp_search.
* Allows changing graph output.
*
* @param string $canonical - Not optimized URL.
* @return string
* @param array $graph - Graph output array.
* @return array
*/
public function canonical( $canonical ) {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
foreach ( $_GET as $key => $value ) {
if ( 'vp_page' === $key || 'vp_filter' === $key || 'vp_sort' === $key || 'vp_search' === $key ) {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
$canonical = add_query_arg( array_map( 'sanitize_text_field', wp_unslash( array( $key => $value ) ) ), $canonical );
public function graph_schema_output( $graph ) {
if ( isset( $graph ) && ! empty( $graph ) && is_array( $graph ) ) {
foreach ( $graph as $key => $graph_item ) {
if ( isset( $graph_item['@type'] ) ) {
switch ( $graph_item['@type'] ) {
case 'BreadcrumbList':
$graph[ $key ]['@id'] = Visual_Portfolio_Archive_Mapping::get_canonical_anchor( $graph_item['@id'] );
break;
case 'WebPage':
case 'CollectionPage':
$graph[ $key ]['@id'] = Visual_Portfolio_Archive_Mapping::get_canonical_anchor( $graph_item['@id'] );
$graph[ $key ]['url'] = Visual_Portfolio_Archive_Mapping::get_canonical( $graph_item['@id'] );
$graph[ $key ]['breadcrumb']['@id'] = Visual_Portfolio_Archive_Mapping::get_canonical_anchor( $graph_item['@id'] );
break;
}
}
}
}
return $canonical;
return $graph;
}

/**
* Set query as archive temporary.
* This is necessary for the plugin to work correctly and set all the necessary settings in the page footer.
* Because our custom archive and taxonomy pages override the base query and interfere with the global object,
* Conflicts may occur with some SEO plugins that work this way.
* In this case, the search plugin is trying to place the assets needed for a regular page in the footer,
* While the page itself is defined as a taxonomy.
* In this case, we let the plugin know that this is not a page, but a category.
*
* @return void
*/
public function set_query_as_archive() {
if ( Visual_Portfolio_Archive_Mapping::is_category() ) {
global $wp_query;

$wp_query->is_archive = true;
$wp_query->is_single = false;
$wp_query->is_singular = false;
$wp_query->is_page = false;
$wp_query->is_post_type_archive = true;
$wp_query->is_category = true;
}
}

/**
* Set query as archive temporary.
* This is necessary for the plugin to work correctly and set all the necessary settings in the page footer.
* Because our custom archive and taxonomy pages override the base query and interfere with the global object,
* Conflicts may occur with some SEO plugins that work this way.
* In this case, the search plugin is trying to place the assets needed for a regular page in the footer,
* While the page itself is defined as a taxonomy.
* In this case, we let the plugin know that this is not a page, but a category.
* This function cancels previous settings so as not to interfere with further system operation.
*
* @return void
*/
public function remove_query_as_archive() {
if ( Visual_Portfolio_Archive_Mapping::is_category() ) {
global $wp_query;

$wp_query->is_archive = false;
$wp_query->is_single = false;
$wp_query->is_singular = true;
$wp_query->is_page = true;
$wp_query->is_post_type_archive = false;
$wp_query->is_category = false;
}
}
}
new Visual_Portfolio_3rd_All_In_One_Seo();
66 changes: 55 additions & 11 deletions classes/3rd/plugins/class-rank-math.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,68 @@ class Visual_Portfolio_3rd_Rank_Math {
*/
public function __construct() {
// Fixed canonical links.
add_filter( 'rank_math/frontend/canonical', array( $this, 'canonical' ) );
add_filter( 'rank_math/frontend/canonical', array( 'Visual_Portfolio_Archive_Mapping', 'get_canonical' ) );
add_filter( 'rank_math/frontend/title', array( $this, 'get_title' ) );
add_filter( 'rank_math/opengraph/facebook/og_title', array( $this, 'get_title' ) );
add_action( 'rank_math/head', array( $this, 'set_query_as_archive' ), 5 ); // priority one level lower than what the plugin uses.
add_action( 'rank_math/head', array( $this, 'remove_query_as_archive' ), 23 ); // priority one level higher than what the plugin uses.
}

/**
* Optimize url by supported GET variables: vp_page, vp_filter, vp_sort and vp_search.
* Allow changing the Rank Math generated title.
*
* @param string $canonical - Not optimized URL.
* @param string $title - Current Page Title.
* @return string
*/
public function canonical( $canonical ) {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
foreach ( $_GET as $key => $value ) {
if ( 'vp_page' === $key || 'vp_filter' === $key || 'vp_sort' === $key || 'vp_search' === $key ) {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
$canonical = add_query_arg( array_map( 'sanitize_text_field', wp_unslash( array( $key => $value ) ) ), $canonical );
}
public function get_title( $title ) {
return Visual_Portfolio_Archive_Mapping::get_current_term_title() ?? $title;
}

/**
* Set query as archive temporary.
* This is necessary for the plugin to work correctly and set all the necessary settings in the page header.
* Because our custom archive and taxonomy pages override the base query and interfere with the global object,
* Conflicts may occur with some SEO plugins that work this way.
* In this case, the search plugin is trying to place the assets needed for a regular page in the header,
* While the page itself is defined as a taxonomy.
* In this case, we let the plugin know that this is not a page, but a category.
*
* @return void
*/
public function set_query_as_archive() {
if ( Visual_Portfolio_Archive_Mapping::is_category() ) {
global $wp_query;

$wp_query->is_archive = true;
$wp_query->is_single = false;
$wp_query->is_singular = false;
$wp_query->is_page = false;
$wp_query->is_post_type_archive = true;
}
}

/**
* Remove query as archive temporary.
* This is necessary for the plugin to work correctly and set all the necessary settings in the page header.
* Because our custom archive and taxonomy pages override the base query and interfere with the global object,
* Conflicts may occur with some SEO plugins that work this way.
* In this case, the search plugin is trying to place the assets needed for a regular page in the header,
* While the page itself is defined as a taxonomy.
* In this case, we let the plugin know that this is not a page, but a category.
* This function cancels previous settings so as not to interfere with further system operation.
*
* @return void
*/
public function remove_query_as_archive() {
if ( Visual_Portfolio_Archive_Mapping::is_category() ) {
global $wp_query;

$wp_query->is_archive = false;
$wp_query->is_single = true;
$wp_query->is_singular = true;
$wp_query->is_page = true;
$wp_query->is_post_type_archive = false;
}
return $canonical;
}
}
new Visual_Portfolio_3rd_Rank_Math();
54 changes: 43 additions & 11 deletions classes/3rd/plugins/class-yoast.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,56 @@ class Visual_Portfolio_3rd_Yoast {
*/
public function __construct() {
// Fixed canonical links.
add_filter( 'wpseo_canonical', array( $this, 'canonical' ), 12, 1 );
add_filter( 'wpseo_canonical', array( 'Visual_Portfolio_Archive_Mapping', 'get_canonical' ), 12, 1 );
add_filter( 'wpseo_opengraph_url', array( 'Visual_Portfolio_Archive_Mapping', 'get_canonical' ), 12, 1 );
add_filter( 'wpseo_schema_webpage', array( $this, 'graph_schema_webpage' ), 12, 1 );
add_filter( 'wpseo_schema_breadcrumb', array( $this, 'graph_schema_breadcrumb' ), 12, 1 );
add_filter( 'wpseo_opengraph_title', array( $this, 'graph_title' ), 12, 1 );
}

/**
* Optimize url by supported GET variables: vp_page, vp_filter, vp_sort and vp_search.
* Allows changing webpage graph piece output.
*
* @param string $canonical - Not optimized URL.
* @return string
* @param array $webpage_graph_piece - The webpage graph piece to filter.
* @return array
*/
public function canonical( $canonical ) {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
foreach ( $_GET as $key => $value ) {
if ( 'vp_page' === $key || 'vp_filter' === $key || 'vp_sort' === $key || 'vp_search' === $key ) {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
$canonical = add_query_arg( array_map( 'sanitize_text_field', wp_unslash( array( $key => $value ) ) ), $canonical );
public function graph_schema_webpage( $webpage_graph_piece ) {
$webpage_graph_piece['@id'] = Visual_Portfolio_Archive_Mapping::get_canonical( $webpage_graph_piece['@id'] );
$webpage_graph_piece['url'] = Visual_Portfolio_Archive_Mapping::get_canonical( $webpage_graph_piece['url'] );
$webpage_graph_piece['breadcrumb']['@id'] = Visual_Portfolio_Archive_Mapping::get_canonical_anchor( $webpage_graph_piece['breadcrumb']['@id'] );
$webpage_graph_piece['name'] = Visual_Portfolio_Archive_Mapping::get_current_term_title() ?? $webpage_graph_piece['name'];

if ( ! empty( $webpage_graph_piece['potentialAction'] ) ) {
foreach ( $webpage_graph_piece['potentialAction'] as $key => $potential_action ) {
if ( isset( $potential_action['target'] ) && ! is_array( $potential_action['target'] ) && isset( $potential_action['@type'] ) && 'ReadAction' === $potential_action['@type'] ) {
$webpage_graph_piece['potentialAction'][ $key ]['target'] = Visual_Portfolio_Archive_Mapping::get_canonical( $potential_action['target'] );
}
}
}
return $canonical;

return $webpage_graph_piece;
}

/**
* Allows changing breadcrumb graph piece output.
*
* @param array $breadcrumb_graph_piece - The breadcrumb graph piece to filter.
* @return array
*/
public function graph_schema_breadcrumb( $breadcrumb_graph_piece ) {
$breadcrumb_graph_piece['@id'] = Visual_Portfolio_Archive_Mapping::get_canonical_anchor( $breadcrumb_graph_piece['@id'] );

return $breadcrumb_graph_piece;
}

/**
* Allow changing the Yoast SEO generated title.
*
* @param string $title - Current Graph Title.
* @return string
*/
public function graph_title( $title ) {
return Visual_Portfolio_Archive_Mapping::get_current_term_title() ?? $title;
}
}
new Visual_Portfolio_3rd_Yoast();
Loading

0 comments on commit e7f6b13

Please sign in to comment.