Yoast / wordpress-seo

Yoast SEO for WordPress
https://yoast.com/wordpress/plugins/seo/
Other
1.75k stars 886 forks source link

Compatibility issue with WPVIP Enterprise Search (meta content goes missing) #21171

Closed Ipstenu closed 5 months ago

Ipstenu commented 6 months ago

(this is RELATED TO 19695 and covers ENTERPRISE Search)

Please give us a description of what happened

On VIP they have a fork they made for "Enterprise" Search - https://docs.wpvip.com/enterprise-search/

If you follow their directions here - https://docs.wpvip.com/enterprise-search/enable-non-search-queries/ - it breaks the meta (effectively making Yoast SEO's description, among other seo meta like twitter URLs, canonical URLs, SEO titles, etc empty).

So here, we would be turning ON their Enterprise Search for categories:

function vip_sample_es_offload( $query ) {
    if ( $query->is_main_query() && $query->is_category() ) { // Conditions to offload to ES.
        $query->set( 'es', true );
    }
}
add_action( 'pre_get_posts', 'vip_sample_es_offload' );

And when we do so, the description for categories vanishes. If you make it $query->is_author() then you lose the descriptions for Authors.

To Reproduce

Step-by-step reproduction instructions

  1. Install YoastSEO on a WP VIP site with Enterprise Search Enabled
  2. Apply the VIP recommended code to add EntSearch to categories (or authors)
  3. View source and view meta data

Expected results

  1. Yoast SEO would continue to work and all titles/meta overrides would function

Actual results

  1. Numerous missing metadata compared to without EntSearch

Screenshots, screen recording, code snippet

Author Pages Meta Description is missing (and the title was wrong as well - it was the PRE Yoast title)

Screenshot 2024-02-22 at 11 19 39 AM

Category Pages

Category-Missing-Meta

I don't know how obvious it is, but the meta desc and canonical URL are entirely gone, and much of the data is effectively the NON Yoastified versions 😞

Temporary (we hope) fix for Categories

The only workaround we found was to apply filters for all of the missing data:

add_filter( 'wpseo_metadesc',  array( $this, 'customize_wpseo_metadesc' ) );
add_filter( 'wpseo_opengraph_desc',  array( $this, 'customize_wpseo_opengraph_desc' ) );
add_filter( 'wpseo_canonical', array( $this, 'customize_wpseo_canonical_url' ) );
add_filter( 'wpseo_opengraph_url', array( $this, 'customize_wpseo_canonical_url' ) );
add_filter( 'wpseo_title', array( $this, 'customize_wpseo_title' ) );
add_filter( 'wpseo_opengraph_title', array( $this, 'customize_wpseo_opengraph_title' ) );
add_filter( 'wpseo_twitter_title', array( $this, 'customize_wpseo_twitter_title' ) );
add_filter( 'wpseo_next_rel_link', array( $this, 'customize_wpseo_rel_link' ) );
add_filter( 'wpseo_prev_rel_link', array( $this, 'customize_wpseo_rel_link' ) );

Example Twitter Title fix:

        function customize_wpseo_twitter_title( $title ) {
            if ( ! is_category() ) {
                return $title;
            }

            if ( is_category() ) {
                $term                = get_term( get_queried_object_id() );
                $wpseo_term_meta     = get_option( 'wpseo_taxonomy_meta' );
                $yoast_twitter_title = ( $wpseo_term_meta['category'][ get_queried_object_id() ]['wpseo_twitter-title'] ) ?? '';
                $yoast_seo_title     = ( $wpseo_term_meta['category'][ get_queried_object_id() ]['wpseo_title'] ) ?? '';
                $yoast_title         = ( $yoast_twitter_title ) ?: $yoast_seo_title;

                // If Yoast Title is in play, replace the placeholders.
                if ( ! empty( $yoast_title ) ) {
                    $new_title = $this->replace_customized_wpseo_snippets( $yoast_title, $term->description, $term->name );
                } else {
                    $new_title = ( $title ) ?: $term->name;
                }

                if ( $new_title ) {
                    return $new_title;
                }
            }

            return $title;
        }

Example Rel Link fix:

        function customize_wpseo_rel_link( $link ) {
            if ( is_category() && ! str_contains( $link, get_term_link( get_queried_object() ) ) ) {
                $link = str_replace( '/page/', get_term_link( get_queried_object() ) . 'page/', $link );
            }

            return $link;
        }

replace_customized_wpseo_snippets simply performs the same replacements of snippets that Yoast normally does.

Technical info

Used versions

josevarghese commented 6 months ago

Hi @Ipstenu

Thanks for creating the issue, and I'm very sorry for the delay in responding.

I'm trying to figure out how to replicate this issue as I am unfamiliar with VIP and Enterprise search. I will ask help from our development team to look into this issue in the coming days and keep you posted.

pls78 commented 6 months ago

Hello @Ipstenu! We were able to reproduce the issue locally and we have identified the problem (some query variables are missing in the WP_Query::query_vars array) and we are working on a solution. 🙂

Ipstenu commented 6 months ago

@pls78 That's fantastic! Thank you :)

pls78 commented 5 months ago

Hi @Ipstenu, some updates about this 🙂 Upon additional investigation it seems the problem is the approach ES_WP_Query takes: as written in their documentation:

The gist of what happens whn you use WP_Query( 'es=true' ) is that on pre_get_posts, the query vars are sent to a new instance of ES_WP_Query. The query vars are then replaced with a simple post__in query using the IDs which Elasticsearch found.

What happens is that, once the query has been re-written to be a post__in query, the WP_Query query_vars array is not filled with the correct data (which should be based on the type of content being retrieved, e.g. category, tag... ). Our frontend integration, which takes care of rendering the additional meta fields which goes missing relies on that missing data. It is worth noting that I tried also to deactivate our plugin and just dumping the query_vars array by hooking into wp_head (which is the hook we user for the frontend integration), and the results are the same: some data is missing. Do you perhaps know if this is expected behaviour (WP_Query query_vars being changed)? We have come up with a workaround, but the fact the WP_Query object gets changed might lead to other side effects that have not been discovered yet.

Ipstenu commented 5 months ago

Do you perhaps know if this is expected behaviour (WP_Query query_vars being changed)?

I believe that's as expected from WP VIP. In this moment, we've not done any further changes.

pls78 commented 5 months ago

In this case I think it would be more safe and maintainable if the VIP search adapter for ES_WP_Query (or ES_WP_Query itself?) would take care of re-instating the original data in the query_vars array. Being WP_Query a core WordPress class, hacking its internal state might cause problems also with other plugins that uses it. We have a workaround for your specific issue but, giving the fact that the problem is not in our plugin, I'd like to know your point of view on this and if changes can be made by your side.

Ipstenu commented 5 months ago

@pls78 We have a contact with VIP and can bring this up (obviously we didn't write this code either). Do you have any connections with them as well?

pls78 commented 5 months ago

@Ipstenu Yes, we'll ask about the issue in our shared Slack channel with Automattic.

pls78 commented 5 months ago

@Ipstenu after talking to Automattic developers we have decided to proceed with the implementation of the aforementioned workaround.