I'm using a snippet to overwrite the canonical URL in YoastSEO for WordPress/WooCommerce. The snippet is based on the official docs example: https://developer.yoast.com/features/seo-tags/canonical-urls/api/
Here's my code:
function prefix_filter_canonical_example( $canonical ) {
if (is_shop() && is_paged() ) :
$canonical = get_permalink(woocommerce_get_page_id( 'shop' )).'page/'.get_query_var('paged').'/';
elseif(WCV_Vendors::is_vendor_page()):
$vendor_shop = urldecode( get_query_var( 'vendor_shop' ) );
$vendor_id = WCV_Vendors::get_vendor_id( $vendor_shop );
$canonical = WCV_Vendors::get_vendor_shop_page( $vendor_id );
endif;
return $canonical;
}
add_filter( 'wpseo_canonical', 'prefix_filter_canonical_example' );
The code doesn't do anything to the canonical URL regardless of the content I return. But the if/else works fine and if I echo the content of $canonical I see the correct URLs.
I tried it already with the basic storefront theme and I deactivated nearly all plugins. But the snippet won't work. Is there anything I miss?
If you don't pass any priority to the action wordpress will take it as 10. Yoast SEO also call this filter to add canonical url so wordpress executed function in the order in which they were added to the action.
So change this line
add_filter( 'wpseo_canonical', 'prefix_filter_canonical_example' );
With this
add_filter( 'wpseo_canonical', 'prefix_filter_canonical_example', 20 );
Related
We are working on a localization project in WordPress. In fact, we can correctly add the active browser URL with language support. I'll add the details and the entire code below. Don't worry, my question will not be so open-ended and I will make it more specific.
Step 1
First of all, we should add a variable in the link structure to the WordPress algorithm.
function custom_rewrite_basic_query_vars( $query_vars ){
$query_vars[] = 'lang';
return $query_vars;
}
add_filter( 'query_vars', 'custom_rewrite_basic_query_vars' );
Thus, WordPress detects a variable such as ?lang= and includes it in the query mechanism.
Step 2
Using the "add_rewrite_rule" function, you need to add the variable ?lang= to run in the background of WordPress's persistent link structure.
Easy Example:
/*
LANG PREFIX + INDEX = localhost/en/ = localhost/?lang=en
*/
add_rewrite_rule(
'^(en|fr|de|ru|tr)/?$',
'index.php?lang=$matches[1]',
'top'
);
I will not add the remaining instances one by one, because you should use close to 20 rewrite rules. (Date, Category, Comment, Page, Text, Pagination, etc.)
NOTE: Those who work on such a project and want to use these rules will add it if requested.
Now our persistent connection structure supports variables for the language option.
localhost/en/hello-world
localhost/ru/hello-world
localhost/de/04/07/2019
localhost/fr/page/2
etc. all the links you can think of.
Step 3
If a variable is detected from the browser (for example: lang = en), we will display the contents of the previously saved inter-language translated.
At this point we do not need any support. But when we get to step 4, we're stuck.
Step 4
Activating the prefix language variable that was added before, users when using the links within the site, on all in-site navigation links.
This means that if a user has access to the localhost/fr/hello-world link, they must reach the localhost/fr/contact link when they return to the Home Page or click the Contact link.
To do this, you need to add the language prefix that is currently active in the browser to all in-site links.
Unfortunately, this is the only point where we hang out and we can't find a solution.
In fact, we tried most things before writing here. (Of course within our knowledge). We even looked at plug-ins that offer some language support.
e.g. <WP Multilang>
Of course, it's so complicated and so much code. We didn't even understand the plug-in.
There is, of course, a logical way of doing this, and I hope that person sees this post and answers. Thank you sincerely for all your supports.
One step to Answer
After a while, I reached the following code and confirmed that it was working correctly.
<?php
function link_fn( $url ){
$lang = get_query_var('lang', false);
if( $lang !== false && strpos( $url, $lang ) !== false )
$url = $url . $lang . '/';
return $url;
}
add_filter( 'shortcut_link', 'link_fn' );
add_filter( 'post_link', 'link_fn' );
add_filter( 'page_link', 'link_fn' );
add_filter( 'post_type_link', 'link_fn' );
add_filter( 'attachment_link', 'link_fn' );
add_filter( 'term_link', 'link_fn' );
add_filter( 'author_link', 'link_fn' );
add_filter( 'post_type_archive_link', 'link_fn' );
add_filter( 'day_link', 'link_fn' );
add_filter( 'month_link', 'link_fn' );
add_filter( 'year_link', 'link_fn' );
But at this point, I came across a problem. Here we get data like "localhost/hello-world/[LANG]/".
What I want is "localhost/[LANG]/hello-world".
To resolve this situation, you must add a REGEX query to the existing URL structure, if it does not contain the LANG, add the language code to the BASE URL. As a REGEX query should be added, I could not do this...
I not want to answer my own question and confirm. In addition to the code I have written above, if there is an answer containing the query I want, I will mark it as the answer.
Answer
function link_fn( $url ){
$lang = get_query_var('lang', false);
$site_url = get_option('home');
if( $lang !== false )
{
$new_url = str_replace( $site_url, "", $url );
if( preg_match('/\b$lang\b/', $new_url) !== false )
{
$url = $site_url."/".$lang.$new_url;
}
}
return $url;
}
add_filter( 'home_url', 'link_fn' );
You got really far. Very nice effort
I understand that what's between you and victory is only to change the outcome link structure?
If yes, here is a solution:
function link_fn($url){
$lang = get_query_var('lang', false);
$url_parts = explode('/', $url);
if ( $lang && in_array($lang, $url_parts) === false) { // lang does not exists in URL
array_splice($url_parts, 1, 0, $lang);
}
$url = implode('/', $url_parts);
return $url;
}
I think one possible approach is to get all the HTML content use ob_start() and ob_get_contents() and then get all the link with regEx.
Note: not all links are post/page, there are some static files too.
Can you language constant be a part of query string instead of path?
instead of
localhost/en/hello-world
like this
localhost/hello-world?lang=en
If so take a look How to pass extra variables in URL with WordPress
I suggest to dig into this direction.
add_action( 'pre_get_posts', 'lang_pre_get_posts', 1 );
function lang_pre_get_posts( $query ) {
if ( is_admin() || ! $query->is_main_query() ){
return;
}
add_query_arg( 'lang', filter_var( $_COOKIE["lang"], FILTER_SANITIZE_STRING ) );
}
I want to create SCO friendly URL in the WordPress. Also, I have added a hook in my functions.php file as below code but not working.
My URL:http://bddlabs.com/webinar01/?id=pzlyglhbepotwpvbigdatadim_data&storyid=Story_997e9391-71d7-4fac-804b-de891c7aa595
I want http://bddlabs.com/webinar01/pzlyglhbepotwpvbigdatadim_data/Story_997e9391-71d7-4fac-804b-de891c7aa595
Is it possible? I am not sure about it. URL query string is coming from the third party, URL query string is coming from the third party, page content render based on query string.
Below code added landing-page-15.php it WordPress theme base page template
function fb_change_search_url_rewrite() {
if ( ! empty( $_GET['storyid'] ) ) {
wp_redirect( home_url( "/webinar01/" ) . urlencode( get_query_var( 'storyid' ) ) );
load_template( realpath(__DIR__ . '/..') . '/landing-page-15.php' );
exit();
}
}
add_action( 'template_redirect', 'fb_change_search_url_rewrite' );
//additional rewrite rule + pagination tested
function rewrite_search_slug() {
set_query_var('storyid', $_GET['storyid']);
add_rewrite_rule(
'find(/([^/]+))?(/([^/]+))?(/([^/]+))?/?',
'index.php?id=$matches[2]&storyid=$matches[6]',
'top'
);
}
add_action( 'init', 'rewrite_search_slug' );
You may consider using WordPress builtin permalinks option located in Settings tab.
Set %category%/%postname%/ so that permalink should work as per your requirements.
When posting new content, select a sub category and put post title the same you want to appear in your permalink.
Hope it answers your question.
Wordpress can do this by default. https://codex.wordpress.org/Using_Permalinks
So I'm trying to remove the canonical link in the header of WordPress for paginated pages but all the suggestions I tried aren't working.
Here is my code which is in my functions.php file:
function my_add_noindex_tags(){
$paged = intval( get_query_var( 'paged' ) );
if(is_search() || is_404() ) :
echo '<meta name="robots" content="noindex,follow">';
endif;
if ($paged >= 2) :
add_filter( 'wpseo_canonical', '__return_false', 10, 1 );
remove_action('wp_head', 'rel_canonical');
echo '<meta name="robots" content="noindex,follow">';
endif;
}
add_action('wp_head','my_add_noindex_tags', 4 );
I know the code inside if ($paged >= 2) : runs because this tag <meta name="robots" content="noindex,follow"> is in the head section.
Anyone know where I might be going wrong.
The issue here is the canonical link added by Yoast SEO aren't properly removed as expected.
Cheers
After going through the Yoast SEO codes, it seems like the canonical action is added to wpseo_head action.
You either have to use priority 1 when adding your function to run in wp_head to get this to execute properly, or do it with the appropriate method below ie. using wpseo_head action.
function remove_canonical() {
$paged = intval( get_query_var( 'paged' ) );
if ($paged >= 2) {
add_filter( 'wpseo_canonical', '__return_false', 10 );
}
}
add_action( 'wpseo_head', 'remove_canonical', 4);
For me only adding this to init action worked
add_action('init', function() {
add_filter( 'wpseo_canonical', '__return_false', 10 );
});
All these answers didn't help me and i couldn't find the right answer for my scenario:
I had to set priority to higher than 10 because apparently Yoast changes the url at priority 10 so if you want to change their url you have to set a higher priority:
Change the canonical url with a custom function:
add_filter( 'wpseo_canonical', 'change_canonical', 20 );
Delete the canonical url:
add_filter( 'wpseo_canonical', '__return_false', 20 );
Be aware that if you do not set a priority it will use priority 10 as the default and it will not work.
I know I'm late to the party, but for the right implementation, you need to run 'wpseo_canonical' filter directly:
function remove_canonical_pagination() {
$paged = intval( get_query_var( 'paged' ) );
if ($paged >= 2) {
return false;
}
}
add_action( 'wpseo_canonical', 'remove_canonical_pagination', 4);
I'm running the latest Wordpress with WooCommerce
I'm trying to customise my search results when I use the search bar in the header of my site.
This is how the results appear when doing a normal search:
http://www.sunshinetrading.com/snowmasters/?s=snow
This is how they should appear, when I search through WooCommerce.
http://www.sunshinetrading.com/snowmasters/?s=snow&post_type=product
What I need to do is automatically append &post_type=product onto every search query launched from the header.
My attempts at a solution:
I added this to my child theme's functions.php file, to try and append the query which would fix everything.
// Search WooCommerce
function search_filter($query) {
if ( !is_admin() && $query->is_main_query() ) {
if ($query->is_search) {
echo esc_url( add_query_arg( 'post_type', 'product' ) );
$query->set('post_type', 'product');
}
}
}
add_action('pre_get_posts','search_filter');
However, when I do this, and do a search, what the URL should be appears briefly as text on the page, before the website proceeds to load exactly the same page as before.
What am I doing wrong? Maybe I could solve this problem by editing the .htaccess file. I've added the following ...
# REWRITE SNOWMASTERS SEARCH
RedirectMatch 302 snowmasters.com.au/?s=(.*) http://snowmasters.com.au/?s=$1&post_type=product
This should redirect http://snowmasters.com.au/?s=snow to http://snowmasters.com.au/?s=snow&post_type=product
But it's not working?
I would appreciate your help Stack Overflow community :)
Thanks
Did you try this function already?
add_query_arg( 'post_type', 'product', 'http://www.sunshinetrading.com/' );
You can also register you query string var in wordpress like this:
function add_query_vars_filter( $qVars ){
$qVars[] = "post_type";
return $qVars;
}
add_filter( 'query_vars', 'add_query_vars_filter' );
This is from the codex: https://codex.wordpress.org/Plugin_API/Filter_Reference/query_vars
Reposted due to no replies.
I'm having some trouble setting a custom canonical title using the Wordpress SEO API: http://yoast.com/wordpress-seo-api-docs/
I have a custom post type called designs which uses a custom URL rewrite. It takes the base page /design/ and adds the design name to it like /design/a-design/. The canonical in Wordpress SEO by default is the /design/ page.
What I want to do is write a function which determines if it is a design page and return a different canonical. I can test whether it's a design page by doing if ($design == ""){ and I tried to use the custom permalink URL, but the function just removes the canonical completely.
Here's my basic function:
function design_canonical(){
if ($design == "") {
// Leave blank and Yoast SEO will use default canonical for posts/pages
}
else {
return $design['detailslink'];
}
}
add_filter( 'wpseo_canonical', 'design_canonical' )
Quite clearly doing something wrong, but I'm not entirely sure what.
Thoughts?
You could try something like:
function design_canonical($url) {
global $post;
if ( get_post_type( $post->ID ) == 'design' ) {
return site_url( '/design/' . $post->post_name );
} else {
// Do nothing and Yoast SEO will use default canonical for posts/pages
return $url;
}
}
add_filter( 'wpseo_canonical', 'design_canonical' );
Hi i couldn't answer to the above post so I just make another one.
I tried to use the answer from stealthyninja for a similar problem and it almost worked. Except the last part: the empty else statement. It renders no output if the rule doesn't match.
Maybe Yoast updated his plugin on this within the last 2 years so I thought I should mention it here.
The following Code-Snippet solved my problem:
function design_canonical($url) {
global $post;
if ( get_post_type( $post->ID ) == 'design' ) {
return site_url( '/design/' . $post->post_name );
} else {
return $url;
}
}
add_filter( 'wpseo_canonical', 'design_canonical' );