• Resolved Marc

    (@arbolife)


    Hi Sybre,

    Now that we have GeoDirectory live on our site, I have a lot of custom post types I’d like to have control on how the SEO Title, Description & Social image gets put together. Also our site is multilingual, so I’d like to take that into account as well.

    I searched your website and looked in the extensions and didn’t find anything for that. Could you give some pointers of where I could start ?

    I have two examples where I’d like to improve results:

    1. A Directory entry like this one: https://www.arbolife.com/fr/restaurants/switzerland/neuchatel/montezillon/laubier/
    og:title ArboLife | L’Aubier
    og:description La cuisine est certifiée bio et bio-dynamique. Privilège des provenances locales. Les produits laitiers viennent presque exclusivement de leur ferme, les viandes en grande partie, tout comme les…

    This is generated automatically from the title and description of the post. It would be great to be able make the “automatic” output look like this (based on the custom post type):
    og:title Annuaire ArboLife | Restaurant à Montezillon: L’Aubier
    og:description Les Murailles 5, Montezillon, Suisse (Choix végan, choix végétarien, choix sans lactose, aliments bio). Aliments locaux La cuisine est certifiée bio et bio-dynamique. Privilège des provenances locales…

    This would pull the word “Restaurant” based on the custom post type, then the address and the categories for the description would come from custom fields of the listing.

    2. A category page: https://www.arbolife.com/fr/restaurants/aliments-bio/ outputs this:
    og:title ArboLife | Annuaire – Catégorie de restaurants: Aliments Bio
    og:description Parcours l’annuaire à la recherche de restaurants proposants des mets cuisinés à partir d’ingrédients provenant de l’agriculture biologique.

    This is great, but it has no image. The category has both a pin and a default image assigned in GeoDirectory. It would be very useful to have the same field available for inserting a fall-back URL for an image like you just added to the pages and posts (so great).

    I’d be happy to pay for a premium subscription for something like this, meanwhile, are there filters that could be used to achieve this in my functions.php ?

    Best,
    Marc

Viewing 7 replies - 1 through 7 (of 7 total)
  • Plugin Author Sybre Waaijer

    (@cybr)

    Hi Marc,

    There are filters to achieve exactly what you wish.

    I’ll need to collect the required filters to output this information and I’ll be happy to process this tomorrow.

    Until then! Cheers ??

    Plugin Author Sybre Waaijer

    (@cybr)

    Hi Marc,

    I have made a few sketches for you.

    The nature of your request is quite advanced; I’d suggest hiring a developer in the future to handle such specific requests.

    Note: All code below is untested and is made up from abstraction and are because of the request’s nature “quick and dirty”. Use it as a template, and feel free to contribute a better working version.

    So, here is the template for the social title:

    add_filter( 'the_seo_framework_pro_add_title', 'my_custom_og_title', 10, 3 );
    function my_custom_og_title( $title = '', $args = array(), $escape = true ) {
    	
    	if ( $args['meta'] ) {
    		//* Only adjust social titles
    		$blogname = the_seo_framework()->get_blogname();
    		$separator = the_seo_framework()->get_title_separator();
    
    		$post_type = get_query_var( 'post_type' );
    		if ( is_array( $post_type ) )
    			$post_type = reset( $post_type );
    
    		$post_type_obj = get_post_type_object( $post_type );
    		if ( isset( $post_type_obj->labels ) ) {
    			$post_type_name = $post_type_obj->labels->name;
    		} else {
    			$post_type_name = '';
    		}
    
    		if ( $post_type_name ) {
    			$replacement = sprintf( '%s %s: %s', $separator, $post_type_name, $blogname );
    			
    			$title = str_replace( "$separator $blogname", $replacement, $title );
    		}
    	}
    	
    	return $title;
    }
    

    For the image, there’s the following template. You’d have to manually adjust the image URL and ‘my_post_type’ to your post type.

    add_filter( 'the_seo_framework_ogimage_output', 'my_og_image_output', 10, 2 );
    function my_og_image_output( $image = '', $id = 0 ) {
    		
    	$locale = get_locale();
    	$post_type = get_post_type();
    	$scheme = is_ssl() ? 'https' : 'http';
    	
    	if ( 'fr_FR' === $locale && 'my_post_type' === $post_type ) {
    		$image = 'https://example.com/path/to/my/french/img.jpg';
    	} elseif ( 'en_US' === $locale && 'my_post_type' === $post_type ) {
    		$image = 'https://example.com/path/to/my/english/img.jpg';
    	}
    	
    	return esc_url( $image, array( $scheme ) );
    }

    Unfortunately, I’m unable to automate the description per your request. As I do not have the variables. In any case, you could forward these filters to your developer:

    the_seo_framework_description_output
    the_seo_framework_ogdescription_output
    the_seo_framework_twitterdescription_output

    I hope this helps ?? Cheers!

    Thread Starter Marc

    (@arbolife)

    Hi Sybre,

    Thank you so much, that was really useful. I’m not a developer, but it’s fun to poke around with code. I’ve got a version working to change the title & description of all GeoDirectory custom post types and switching between English and French using WPML. Here’s my code:

    /******************************************************************
     * Edit the title for both the header and social networks
     ******************************************************************/
    add_filter( 'the_seo_framework_pro_add_title', 'arbolife_custom_title', 10, 3 );
    
    function arbolife_custom_title( $title = '', $args = array(), $escape = true ) {
        global $post;
        $blogname = the_seo_framework()->get_blogname();
        $separator = the_seo_framework()->get_title_separator();
        
        // Get the current post type
        $post_type = get_post_type( $post->ID );
        
        // Get all the GeoDirectory post types
        $all_gd_post_type  = geodir_get_posttypes();    
        // If the post type is a GeoDirectory post type & we're not in a category page
        if ( in_array($post_type, $all_gd_post_type, true) ) {
    		$post_type_obj = get_post_type_object( $post_type );
    		if ( isset( $post_type_obj->labels ) ) {
    			$post_type_name = $post_type_obj->labels->singular_name;
    		} else {
    			$post_type_name = '';
    		}
        
            $directory_name = __( '%s Directory', 'arbolife-seo' );
            $directory_full = sprintf($directory_name, $blogname); 
            
            // If there is a city AND a post type name 
            //   AND the page is not an archive (displaying a cateogry)
            //   AND the page is not a search result
            if ( $post->post_city && $post_type_name && !is_archive() && !is_search() ){ 
                $type_in_city = __( ' - %s in %s', 'arbolife-seo' );
                $post_type_location = sprintf($type_in_city, $post_type_name, $post->post_city); 
            // Same as above but no city (most likely online store)    
            } else if ( $post_type_name && !is_archive() && !is_search() ){
                $post_type_location = sprintf( ' - %s', $post_type_name);
            } else {
                $post_type_location = '';
            }
    		if ( $post_type_name ) {
    			$replacement = sprintf( '% s%s %s %s', $post->post_title, $post_type_location, $separator, $directory_full );
    			$title = str_replace( "$blogname $separator", $title, $replacement );   
    		}
    	}
    	return $title;
    }
    
    /******************************************************************
     * Edit the description for both the meta tag and og for social networks
     ******************************************************************/
    add_filter( 'the_seo_framework_description_output', 'arbolife_custom_description', 10, 3 );
    add_filter( 'the_seo_framework_ogdescription_output', 'arbolife_custom_description', 10, 3 );
    
    function arbolife_custom_description( $description = '', $args = array() ) {
        global $post;
        
        // Get the current post type
        $post_type = get_post_type( $post->ID );
        
        // Get all the GeoDirectory post types
        $all_gd_post_type  = geodir_get_posttypes();    
        // If the post type is a GeoDirectory post type & we're not in a category page & not in search page
        if ( in_array($post_type, $all_gd_post_type, true)  && !is_archive() && !is_search() ) {
    		
      
            // If there is a city (not an online store) 
            if ( $post->post_city ){ 
                $country_name = __( $post->post_country, 'arbolife-seo' );
                $post_location = sprintf( '%s, %s, %s - ', $post->post_address, $post->post_city, $country_name ); 
            // Same as above but no city (most likely online store)    
            } else {
                $post_location = '';
            }
            
            // Get the list of categories
            $post_tax = $post_type . "category";
            $post_categories = $post->{$post_tax};
            if (is_array($post_categories)) {
                $post_categories = implode(', ', $post_categories);
            }
            $cats_arr = array_filter(explode(",", $post_categories));
            $category_list = '';
            foreach ($cats_arr as $cat) {
                $term_arr = get_term($cat, $post_tax);
                if ( !empty($category_list) ) {
                    $category_list .= ', ';
                }
                $category_list .= strtolower($term_arr->name);
            }
           
            // Collate location and categories and create exceprt 
            $initial_replacement = $post_location . ucfirst($category_list);
            $excerpt_length = 170 - strlen($initial_replacement);
            $post_excerpt = text_truncate($post->post_content, $excerpt_length);
            
            // Put the final description together
    		$description = sprintf( '%s | %s', $initial_replacement, $post_excerpt );   
    	}
    	return $description;
    }
    
    /******************************************************************
     * Function to truncate a post description
     ******************************************************************/
    function text_truncate($text,$numb) {
    if (strlen($text) > $numb) { 
      $text = substr($text, 0, $numb); 
      $text = substr($text,0,strrpos($text," ")); 
      $etc = "...";  
      $text = $text.$etc; 
      }
    return $text; 
    }

    The only problem I found is that in the wp-admin area, when viewing a French listing, the title shows with the English wording (“Directory” instead of “Annuaire”, “Store” instead of “Magasin” and “in” instead of “à”. Here’s a screenshot. It’s strange that it works on the frontend, but not the backend, can this be fixed somehow?

    Next I’ll move to fixing the images.

    Best,
    Marc

    • This reply was modified 8 years, 1 month ago by Marc.
    Plugin Author Sybre Waaijer

    (@cybr)

    Hi Marc,

    I’ll need to look into the way the code behaves in the back-end. Because it’s handled in multiple layers, I can’t give you a concrete answer before diving into it.

    On the bright side, a happy inconvenience… This is something I’ll need to do for the upcoming patch, as there is a bug to be fixed:
    https://github.com/sybrew/the-seo-framework/issues/71

    With that, the generation should be ironed out and your code should then also work in the back-end.
    But until then, I’m afraid you’d have to manually check the front-end output.

    Cheers!

    Thread Starter Marc

    (@arbolife)

    Hi Sybre,

    Thanks for you answer. This is “convenient” for me, no problem for waiting until this can be sorted out.

    I looked at the bug link you sent and it made me wonder about one more improvement I could include in my code (but would need a pointer about how to achieve it). Could I make part of my customized title & description be a floating prefix in the backend ?

    For example if my generated description is like this: <meta property=”og:description” content=”Rue Pré-du-Marché 13, Lausanne, Switzerland – Vegetarian, vegan options, organic food | La Cuisine propose des boissons chaudes, dont un délicieux Tcha? maison, à…”>, I’d like to have this part “Rue Pré-du-Marché 13, Lausanne, Switzerland – Vegetarian, vegan options, organic food | ” be a floating prefix so users can adjust only the comment part in the back-end without retyping the whole first part.

    Would this be another filter to use ?

    Best,
    Marc

    Plugin Author Sybre Waaijer

    (@cybr)

    Hi Marc,

    What you wish to achieve has to do with JavaScript manipulation.

    Currently, the JavaScript built for The SEO Framework is targeted as-is, and maintains no room for alteration. In 2.8 some states (properties) have been opened up (view them in the externs file), but not executing code.

    This doesn’t mean your request is impossible, but there’s currently no “easy” way to do this. If anything, whatever will be build will be “hackish” and shall tend to break easily in updates for there is no support.
    In fact, what you want has to be written from the ground up.

    Although my answer is very technical, I do hope this clears things up.

    If you want to pursue your wish, feel free to open up a feature request through a GitHub issue and I’ll see what I can do ??

    Cheers!

    Thread Starter Marc

    (@arbolife)

    Hi Sybre,

    Thanks I submitted it on GitHub.

    Cheers,
    Marc

Viewing 7 replies - 1 through 7 (of 7 total)
  • The topic ‘Title & Description structure per custom post types’ is closed to new replies.