• Resolved arypneta

    (@arypneta)


    We have some pages that are creating using WordPress’ add_rewrite_rule capabilities. The pages are working great, but we’ve realized that there was an issue with the SEO and social sharing information. Using various TSF actions, we were able to add things like description, image, etc. as needed for these pages. However, we are still having issues with the canonical URL and og:url on those pages.

    They don’t show up at all with our normal site settings. After doing some searching, it sounds like WordPress doesn’t automatically add canonical urls for pages generated by rewrite rules (or at least for these ones, which are basically redirecting to index.php with some special query parameters to generate the page).

    So, I did some searching in the forum and found this post: https://wordpress.org/support/topic/programmatically-alter-canonical-urls/. Unfortunately, home_link, post_link, and get_canonical_url don’t seem to do the job (some of them don’t even seem to be triggered on this page).

    I noted that the two actions listed later in that post (the_seo_framework_rel_canonical_output and the_seo_framework_ogurl_output) are now deprecated and have been replaced by the_seo_framework_meta_render_data.

    I was able to successfully set both the canonical url and the og:url for these rewrite pages using the_seo_framework_meta_render_data, but I’m not sure if that’s the proper way to do it. From the post I found, it sounds like it would be better to get WordPress to set the canonical URL first (then TSF would do its thing automatically), but I’m not sure if that’s possible in this case.

    Any insight or suggestions you could provide about the best way to do this would be helpful!

    • This topic was modified 1 month ago by arypneta.
Viewing 6 replies - 1 through 6 (of 6 total)
  • Plugin Author Sybre Waaijer

    (@cybr)

    Hello!

    Your research is sound. It’s often better to use higher-level APIs that take care of the rewrite rules and other structures for you, such as by registering a post type. This would ensure all plugins can cooperate with your custom implementation out of the box.

    Nevertheless, could you please share the code you used to create the rewrite rules and explain their intention?

    If you add the following constant to wp-config.php, TSF will display its determined query in the footer of your website. I’m curious about what it says on your custom pages.

    define( 'THE_SEO_FRAMEWORK_DEBUG', true );
    
    Thread Starter arypneta

    (@arypneta)

    It’s a little convoluted, but basically we have our main website where we have a custom post type called Books (“b”). We use that to enter books from authors associated with our organization as well as ones we publish ourselves.

    We have a separate website for our actual publishing entity and the purpose of the rewrite rules is to basically pull the books data from the main site into books page on the publisher site for just the books that are published by us (we use a custom taxonomy to target them). That way, we only have to enter the data once and it will automatically sync. We have an API set up and use a shortcode to pull all the data from the API and display it.

    Obviously, since we use a shortcode, I’m assuming that’s the reason there is no content or image, etc. in <head>. So, I’ve hooked into the SEO framework to add the description and image and title.

    Here’s the relevant rewrite rule. Basically, looks for any page that is siteurl.org/b and gets whatever is after the b and uses that as the slug to query the api. So siteurl.org/b/test-book would look for a book post type with slug test-book on our main site.

    add_rewrite_rule('(b)/([^/]+)/?$', 'index.php?pressbook=$matches[2]', 'top');

    I’ve anonymized the debug output, but here it is with TSF functions:

    <!-- The SEO Framework by Sybre Waaijer -->
    <meta name="robots" content="noindex,max-snippet:-1,max-image-preview:large,max-video-preview:-1" />
    <meta name="description" content="This is definitely a test book. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." />
    <meta property="og:type" content="website" />
    <meta property="og:locale" content="en_US" />
    <meta property="og:site_name" content="Test Press Site" />
    <meta property="og:title" content="Test Book" />
    <meta property="og:description" content="This is definitely a test book. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam…" />
    <meta property="og:image" content="https://siteurl.org/m/2024/06/Test-image-830x1000.png" />
    <meta name="twitter:card" content="summary_large_image" />
    <meta name="twitter:title" content="Test Book" />
    <meta name="twitter:description" content="This is definitely a test book. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam…" />
    <meta name="twitter:image" content="https://siteurl.org/m/2024/06/Test-image-830x1000.png" />
    <script type="application/ld+json">{"@context":"https://schema.org","@graph": [{"@type":"WebSite","@id":"https://siteurl.org/press/#/schema/WebSite","url":"https://siteurl.org/press/","name":"Test Press Site","inLanguage":"en-US","potentialAction": {"@type":"SearchAction","target": {"@type":"EntryPoint","urlTemplate":"https://siteurl.org/press/search/{search_term_string}/"},"query-input":"required name=search_term_string"},"publisher": {"@type":"Organization","@id":"https://siteurl.org/press/#/schema/Organization","name":"Test Press Site","url":"https://siteurl.org/press/","logo":"https://siteurl.org/m/2024/06/Test-image-830x1000.png"}},{"@type":"WebPage","name":"Test Book","description":"This is definitely a test book. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.","inLanguage":"en-US","isPartOf": {"@id": "https://siteurl.org/press/#/schema/WebSite"}}]}</script>
    <link rel="canonical" href="https://siteurl.org/press/b/test-book/" />
    <meta property="og:url" content="https://siteurl.org/press/b/test-book/" />
    <!-- / The SEO Framework by Sybre Waaijer | 4.76ms meta | 1.35ms boot -->
    
    WordPress Query at Meta Generation
    
    Generated in: 0.00051 seconds
    
    cache_version => (string) 'yup'
    has_assigned_page_on_front => (boolean) true
    has_page_on_front => (boolean) true
    page => (integer) 1
    paged => (integer) 1
    query_supports_seo => (boolean) true
    admin_post_type => (string) ''
    current_post_type => (boolean) false
    current_taxonomy => (string) ''
    get_post_type => (boolean) false
    get_post_type_real_id => (boolean) false
    has_blog_page => (boolean) false
    is_404 => (boolean) false
    is_admin => (boolean) false
    is_archive => (boolean) false
    is_attachment => (boolean) false
    is_author => (boolean) false
    is_blog => (boolean) false
    is_blog_as_page => (boolean) false
    is_category => (boolean) false
    is_customize_preview => (boolean) false
    is_date => (boolean) false
    is_day => (boolean) false
    is_feed => (boolean) false
    is_month => (boolean) false
    is_multipage => (boolean) false
    is_page => (boolean) false
    is_post_edit => (boolean) false
    is_post_type_archive => (boolean) false
    is_post_type_archive_supported => (boolean) false
    is_post_type_supported => (boolean) false
    is_preview => (boolean) false
    is_product => (boolean) false
    is_protected => (boolean) false
    is_query_exploited => (boolean) false
    is_real_front_page => (boolean) false
    is_robots => (boolean) false
    is_search => (boolean) false
    is_seo_settings_page => (boolean) false
    is_shop => (boolean) false
    is_single => (boolean) false
    is_singular => (boolean) false
    is_singular_archive => (boolean) false
    is_static_front_page => (boolean) false
    is_tag => (boolean) false
    is_tax => (boolean) false
    is_taxonomy_disabled => (boolean) false
    is_taxonomy_supported => (boolean) false
    is_term_edit => (boolean) false
    is_term_meta_capable => (boolean) false
    is_wp_lists_edit => (boolean) false
    is_year => (boolean) false
    numpages => (integer) 0
    page_id => (integer) 0
    wp_doing_ajax => (boolean) false
    wp_doing_cron => (boolean) false
    wp_is_rest => (boolean) false
    Current WordPress Query
    
    Generated in: 0.00025 seconds
    
    cache_version => (string) 'nope'
    has_assigned_page_on_front => (boolean) true
    has_page_on_front => (boolean) true
    page => (integer) 1
    paged => (integer) 1
    query_supports_seo => (boolean) true
    admin_post_type => (string) ''
    current_post_type => (boolean) false
    current_taxonomy => (string) ''
    get_post_type => (boolean) false
    get_post_type_real_id => (boolean) false
    has_blog_page => (boolean) false
    is_404 => (boolean) false
    is_admin => (boolean) false
    is_archive => (boolean) false
    is_attachment => (boolean) false
    is_author => (boolean) false
    is_blog => (boolean) false
    is_blog_as_page => (boolean) false
    is_category => (boolean) false
    is_customize_preview => (boolean) false
    is_date => (boolean) false
    is_day => (boolean) false
    is_feed => (boolean) false
    is_month => (boolean) false
    is_multipage => (boolean) false
    is_page => (boolean) false
    is_post_edit => (boolean) false
    is_post_type_archive => (boolean) false
    is_post_type_archive_supported => (boolean) false
    is_post_type_supported => (boolean) false
    is_preview => (boolean) false
    is_product => (boolean) false
    is_protected => (boolean) false
    is_query_exploited => (boolean) false
    is_real_front_page => (boolean) false
    is_robots => (boolean) false
    is_search => (boolean) false
    is_seo_settings_page => (boolean) false
    is_shop => (boolean) false
    is_single => (boolean) false
    is_singular => (boolean) false
    is_singular_archive => (boolean) false
    is_static_front_page => (boolean) false
    is_tag => (boolean) false
    is_tax => (boolean) false
    is_taxonomy_disabled => (boolean) false
    is_taxonomy_supported => (boolean) false
    is_term_edit => (boolean) false
    is_term_meta_capable => (boolean) false
    is_wp_lists_edit => (boolean) false
    is_year => (boolean) false
    numpages => (integer) 0
    page_id => (integer) 0
    wp_doing_ajax => (boolean) false
    wp_doing_cron => (boolean) false
    wp_is_rest => (boolean) false

    And here it is with no TSF functions added:

    <!-- The SEO Framework by Sybre Waaijer -->
    <meta name="robots" content="noindex,max-snippet:-1,max-image-preview:large,max-video-preview:-1" />
    <meta property="og:type" content="website" />
    <meta property="og:locale" content="en_US" />
    <meta property="og:site_name" content="Test Press Site" />
    <meta property="og:title" content="Untitled" />
    <meta name="twitter:card" content="summary_large_image" />
    <meta name="twitter:title" content="Untitled" />
    <script type="application/ld+json">{"@context": "https://schema.org","@graph": [{"@type": "WebSite","@id": "https://siteurl.org/press/#/schema/WebSite","url": "https://siteurl.org/press/","name": "Test Press Site","inLanguage": "en-US","potentialAction": {"@type": "SearchAction","target": {"@type": "EntryPoint","urlTemplate": "https://siteurl.org/press/search/{search_term_string}/"},"query-input": "required name=search_term_string"},"publisher": {"@type": "Organization","@id": "https://siteurl.org/press/#/schema/Organization","name": "Test Press Site","url": "https://siteurl.org/press/"}},{"@type": "WebPage","name": "Untitled - Test Press Site","inLanguage": "en-US","isPartOf": {"@id": "https://siteurl.org/press/#/schema/WebSite"}}]}</script>
    <!-- / The SEO Framework by Sybre Waaijer | 1.16ms meta | 1.69ms boot -->
    
    WordPress Query at Meta Generation
    
    Generated in: 0.00039 seconds
    
    cache_version => (string) 'yup'
    has_assigned_page_on_front => (boolean) true
    has_page_on_front => (boolean) true
    page => (integer) 1
    paged => (integer) 1
    query_supports_seo => (boolean) true
    admin_post_type => (string) ''
    current_post_type => (boolean) false
    current_taxonomy => (string) ''
    get_post_type => (boolean) false
    get_post_type_real_id => (boolean) false
    has_blog_page => (boolean) false
    is_404 => (boolean) false
    is_admin => (boolean) false
    is_archive => (boolean) false
    is_attachment => (boolean) false
    is_author => (boolean) false
    is_blog => (boolean) false
    is_blog_as_page => (boolean) false
    is_category => (boolean) false
    is_customize_preview => (boolean) false
    is_date => (boolean) false
    is_day => (boolean) false
    is_feed => (boolean) false
    is_month => (boolean) false
    is_multipage => (boolean) false
    is_page => (boolean) false
    is_post_edit => (boolean) false
    is_post_type_archive => (boolean) false
    is_post_type_archive_supported => (boolean) false
    is_post_type_supported => (boolean) false
    is_preview => (boolean) false
    is_product => (boolean) false
    is_protected => (boolean) false
    is_query_exploited => (boolean) false
    is_real_front_page => (boolean) false
    is_robots => (boolean) false
    is_search => (boolean) false
    is_seo_settings_page => (boolean) false
    is_shop => (boolean) false
    is_single => (boolean) false
    is_singular => (boolean) false
    is_singular_archive => (boolean) false
    is_static_front_page => (boolean) false
    is_tag => (boolean) false
    is_tax => (boolean) false
    is_taxonomy_disabled => (boolean) false
    is_taxonomy_supported => (boolean) false
    is_term_edit => (boolean) false
    is_term_meta_capable => (boolean) false
    is_wp_lists_edit => (boolean) false
    is_year => (boolean) false
    numpages => (integer) 0
    page_id => (integer) 0
    wp_doing_ajax => (boolean) false
    wp_doing_cron => (boolean) false
    wp_is_rest => (boolean) false
    
    Current WordPress Query
    
    Generated in: 0.00023 seconds
    
    cache_version => (string) 'nope'
    has_assigned_page_on_front => (boolean) true
    has_page_on_front => (boolean) true
    page => (integer) 1
    paged => (integer) 1
    query_supports_seo => (boolean) true
    admin_post_type => (string) ''
    current_post_type => (boolean) false
    current_taxonomy => (string) ''
    get_post_type => (boolean) false
    get_post_type_real_id => (boolean) false
    has_blog_page => (boolean) false
    is_404 => (boolean) false
    is_admin => (boolean) false
    is_archive => (boolean) false
    is_attachment => (boolean) false
    is_author => (boolean) false
    is_blog => (boolean) false
    is_blog_as_page => (boolean) false
    is_category => (boolean) false
    is_customize_preview => (boolean) false
    is_date => (boolean) false
    is_day => (boolean) false
    is_feed => (boolean) false
    is_month => (boolean) false
    is_multipage => (boolean) false
    is_page => (boolean) false
    is_post_edit => (boolean) false
    is_post_type_archive => (boolean) false
    is_post_type_archive_supported => (boolean) false
    is_post_type_supported => (boolean) false
    is_preview => (boolean) false
    is_product => (boolean) false
    is_protected => (boolean) false
    is_query_exploited => (boolean) false
    is_real_front_page => (boolean) false
    is_robots => (boolean) false
    is_search => (boolean) false
    is_seo_settings_page => (boolean) false
    is_shop => (boolean) false
    is_single => (boolean) false
    is_singular => (boolean) false
    is_singular_archive => (boolean) false
    is_static_front_page => (boolean) false
    is_tag => (boolean) false
    is_tax => (boolean) false
    is_taxonomy_disabled => (boolean) false
    is_taxonomy_supported => (boolean) false
    is_term_edit => (boolean) false
    is_term_meta_capable => (boolean) false
    is_wp_lists_edit => (boolean) false
    is_year => (boolean) false
    numpages => (integer) 0
    page_id => (integer) 0
    wp_doing_ajax => (boolean) false
    wp_doing_cron => (boolean) false
    wp_is_rest => (boolean) false
    Plugin Author Sybre Waaijer

    (@cybr)

    Thank you for the info!

    TSF won’t output a canonical URL when the page’s robots-meta is populated with “noindex.” This is to help improve deindexing speed.

    Still, even if the “noindex” directive disappeared, the canonical URL of the parent Press page and all subpages would become https://siteurl.org/press/.

    TSF cannot interpret or anticipate the content generated when the shortcode is being parsed. The query parameter you registered inflects the content late after the request is being parsed. The query is empty, as if nothing would be displayed—not even a 404. I believe you made some adjustments to the query based on the pressbook query parameter.

    I once again recommend using custom post types. Then, you can use WordPress’s CMS functionality rather than coding everything yourself and having to clean up left and right. Everything will “just work,” and you can use template files to make something special for the post type, as I have for the KB post type.

    I also made the “Extension” post type, though I filtered the content from the extension readme file. Still, even without the content manually filled within the Editor, WordPress, the theme, and all plugins can anticipate what kind of request we’re dealing with: We know the page ID, the post type, its relation to the post type archive, whether it’s paginated, etc.

    The SEO Framework custom post type query debug information

    Still, I understand that converting your content from a shortcode to a custom post type might be an undertaking. But since TSF doesn’t know what to make of this page, I actually recommend disabling TSF altogether for those requests; it’s now spitting gibberish that’s accidentally somewhat correct, but the Schema.org output causes issues.

    You can disable TSF for a request via filter the_seo_framework_query_supports_seo. In your case, I believe this will do:

    add_filter(
    	'the_seo_framework_query_supports_seo'
    	function ( $supported ) {
    
    		if ( get_query_var( 'pressbook' ) )
    			$supported = false;
    
    		return $supported;
    	},
    );

    You’ll then miss out on all the meta tags TSF generates. But I recommend creating your own for the time being.

    Thread Starter arypneta

    (@arypneta)

    Okay, thanks for all these details. Can you tell me what would make TSF output noindex if it isn’t set on the page already? Looking at the HTML, above the TSF code, robots is set as index and follow. And then the TSF code sets noindex (which overwrites the index setting of course).

    I understand that a custom post type would be better for everything to just work from an SEO standpoint, but the issue is that we want this site to automatically populate from a custom post type at another site. We are entering the same data in a custom post type on another site using WordPress’ CMS and we don’t want to have to duplicate the work on another site.

    Thanks for the snippet about disabling TSF for a particular query. That might be the best approach and we can manually set everything using wp_head (which has the added benefit of being more stable if we ever switched to a different SEO plugin, which isn’t likely of course, but you never know)

    Thanks for your help!

    Plugin Author Sybre Waaijer

    (@cybr)

    Hi again!

    TSF can output “noindex” if it expects an archive, but there are no posts in the archive (at least, not according to WordPress’s “main” Query API). WordPress normally sends a 404 response, but that can be ignored by the theme builder (a bad practice).

    There are several ways to create posts dynamically. Still, from what I understand, by copying over data from one site to the next, you may be creating duplicated content and are competing against yourself.

    Nevertheless, I hope the snippet serves your dynamic content well. Cheers 🙂

    Thread Starter arypneta

    (@arypneta)

    Okay, thanks for all your help and advice!

Viewing 6 replies - 1 through 6 (of 6 total)
  • You must be logged in to reply to this topic.