Plugin Directory

Changeset 808325


Ignore:
Timestamp:
11/21/2013 04:42:12 PM (12 years ago)
Author:
migueluy
Message:

Jetpack: Twitter Cards: Many improvements! props @stephdau

  • Twitter Card tags are no longer based on the Open Graph tags directed at Facebook, except for the title and description if they are already present (but not for media or card type decisions).
  • Actual galleries and posts with multiple images will be treated as the gallery type on twitter, allowing for display of up to 4 images at medium sizes.
  • If a post has a YouTube embed with little to no text, we set the video's poster frame as a medium/banner size image on Twitter (not as large as photo type)
  • We apply the same logic to Vimeo embeds if we found that the poster frame was already saved in post meta by the Open Graph handling (done on publish).
  • If a post has no images at all, we send it as summary, but we try to use the site's blavatar if there is one as a small thumbnail to spruce up the post on twitter, withouth overpowering it.
  • If a post has only one image and is deemed to be a photo post (like for videos, little to no text + only 1 img), we serve it as the photo type, which dislplays a large image on Twitter
  • If a post has 1 to 3 images (but isn't a proper gallery or deemed a single photo post like featured images on long posts), we send it as the summary type, with a small to medium version of the 1st pict to spruce it up on Twitter.
  • See <code>jetpack_disable_twitter_cards</code> filter to disable Twitter Cards altogether.
  • Updated Twitter Cards lib now uses Jetpack_Media_Summary instead of relying on decisions alerady made for the Open Graph tags which migh make sense in Facebook's context, but not Twitter's.
  • See <code>jetpack_open_graph_tags</code> to filter Twitter Cards output, as before.
Location:
jetpack/trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • jetpack/trunk/functions.opengraph.php

    r797292 r808325  
    8686    // Add any additional tags here, or modify what we've come up with
    8787    $tags = apply_filters( 'jetpack_open_graph_tags', $tags, compact( 'image_width', 'image_height' ) );
    88    
     88
    8989    // secure_urls need to go right after each og:image to work properly so we will abstract them here
    9090    $secure = $tags['og:image:secure_url'] = ( empty( $tags['og:image:secure_url'] ) ) ? '' : $tags['og:image:secure_url'];
     
    173173        $image = array( $image );
    174174
     175    $mshot_url_pattern = 'http://s.wordpress.com/mshots/v1/%s?w=534&h=400'; // over twice FB's min size (200), with aspect ratio
     176
    175177    // First fall back, mshots
    176     if ( is_singular() && ! empty( $post ) && is_object( $post ) )
    177         $image[] = 'http://s.wordpress.com/mshots/v1/' . urlencode( get_permalink( $post->ID ) );
     178    /*
     179     if ( is_singular() )
     180        $image[] = sprintf( $mshot_url_pattern, urlencode( get_permalink( $post->ID ) ) );
    178181    else
    179         $image[] = 'http://s.wordpress.com/mshots/v1/' . urlencode( site_url() );
     182        $image[] = sprintf( $mshot_url_pattern, urlencode( site_url() ) );
     183    */
    180184
    181185    // Second fall back, blavatar
     
    218222        }
    219223        $avatar = get_avatar( $email, $width );
    220        
     224
    221225        if ( !$has_filter ) {
    222226            remove_filter( 'pre_option_show_avatars', '__return_true' );
     
    228232        }
    229233    }
    230    
     234
    231235    return $image;
    232236}
  • jetpack/trunk/functions.twitter-cards.php

    r756774 r808325  
    1010 */
    1111function wpcom_twitter_cards_tags( $og_tags ) {
    12     global $post, $wpdb;
     12    global $post;
     13
     14    if ( apply_filters( 'jetpack_disable_twitter_cards', false ) )
     15        return $og_tags;
     16
     17    /*
     18     * These tags apply to any page (home, archives, etc)
     19     */
    1320
    1421    $og_tags['twitter:site'] = '@wordpressdotcom';
     
    1724        return $og_tags;
    1825
    19     $img_count = 0;
    20     foreach ( $og_tags as $key => $value ) {
    21         if ( 'og:image' != $key || ! is_array( $value ) || empty( $value[0] ) )
    22             continue;
     26    /*
     27     * The following tags only apply to single pages.
     28     */
    2329
    24         $img_count = 0;
    25         foreach ( (array) $value as $counter => $image ) {
    26             $og_tags['twitter:image' . $counter] = $image;
    27             $img_count++;
    28             if ( $img_count >= 4 )
    29                 break; // Only 4 images allowed
     30    $card = 'summary';
     31
     32    // Try to give priority to featured images
     33    if ( class_exists('Jetpack_PostImages') ) {
     34        $featured = Jetpack_PostImages::from_thumbnail( $post->ID, 240, 240 );
     35        if ( !empty( $featured ) && count( $featured ) > 0 ) {
     36            if ( (int) $featured[0]['src_width'] >= 280 && (int) $featured[0]['src_height'] >= 150 ) {
     37                $card = 'summary_large_image';
     38                $og_tags['twitter:image:src'] = add_query_arg( 'w', 640, $featured[0]['src'] );
     39            } else {
     40                $og_tags['twitter:image'] = add_query_arg( 'w', 240, $featured[0]['src'] );
     41            }
    3042        }
    3143    }
    3244
    33     // Figure out what kind of card this is, based on the number of images found
    34     if ( 0 == $img_count ) {
    35         // No images = summary
    36         $card = 'summary';
    37     } else if ( $img_count <= 3 ) {
    38         // < 4 images = photo
    39         $card = 'photo';
    40         $og_tags['twitter:image'] = $og_tags['twitter:image0']; // Rename back to photo format (from gallery)
    41         unset( $og_tags['twitter:image0'] );
    42         for ( $i = 1; $i < 4; $i++ ) {
    43             unset( $og_tags['twitter:image' . $i] ); // Remove >0 image references
     45    // Only proceed with media analysis if a featured image has not superseded it already.
     46    if ( empty( $og_tags['twitter:image'] ) && empty( $og_tags['twitter:image:src'] ) ) {
     47        if ( ! class_exists( 'Jetpack_Media_Summary' ) && defined('IS_WPCOM') && IS_WPCOM )
     48            include WP_CONTENT_DIR . '/lib/class.wpcom-media-summary.php';
     49
     50        // Test again, class should already be auto-loaded in Jetpack.
     51        // If not, skip extra media analysis and stick with a summary card
     52        if ( class_exists( 'Jetpack_Media_Summary' ) ) {
     53            $extract = Jetpack_Media_Summary::get( $post->ID );
     54
     55            if ( 'gallery' == $extract['type'] ) {
     56                $card = 'gallery';
     57                $og_tags = wpcom_twitter_cards_gallery( $extract, $og_tags );
     58            } else if ( 'video' == $extract['type'] ) {
     59                // Leave as summary, but with large pict of poster frame (we know those comply to Twitter's size requirements)
     60                $card = 'summary_large_image';
     61                $og_tags['twitter:image:src'] = add_query_arg( 'w', 640, $extract['image'] );
     62            } else {
     63                $img_count = $extract['count']['image'];
     64
     65                if ( empty( $img_count ) ) {
     66                    // No images, use Blavatar as a thumbnail for the summary type.
     67                    if ( function_exists( 'blavatar_domain' ) ) {
     68                        $blavatar_domain = blavatar_domain( site_url() );
     69                        if ( blavatar_exists( $blavatar_domain ) )
     70                            $og_tags['twitter:image'] = blavatar_url( $blavatar_domain, 'img', 240 );
     71                    }
     72                    // Not falling back on Gravatar, because there's no way to know if we end up with an auto-generated one.
     73                } else if ( 1 == $img_count && 'image' == $extract['type'] ) {
     74                        // 1 image = photo
     75                        $card = 'photo';
     76                        $og_tags['twitter:image'] = add_query_arg( 'w', 1400, $extract['image'] );
     77                } else if ( $img_count <= 3 ) {
     78                    // 2-3 images = summary with small to large thumbnail
     79                    $og_tags['twitter:image'] = add_query_arg( 'w', 240, $extract['image'] );
     80                } else if ( $img_count >= 4 ) {
     81                    // >= 4 images = gallery
     82                    $card = 'gallery';
     83                    $og_tags = wpcom_twitter_cards_gallery( $extract, $og_tags );
     84                }
     85            }
    4486        }
    45     } else if ( $img_count >= 4 ) {
    46         // >= 4 images = gallery
    47         $card = 'gallery';
    4887    }
     88
    4989    $og_tags['twitter:card'] = $card;
    5090
     
    5292    if ( ! empty( $post ) && ! empty( $post->post_author ) ) {
    5393        $handle = apply_filters( 'jetpack_sharing_twitter_via', '', $post->ID );
    54         if ( !empty( $handle ) )
     94        if ( !empty( $handle ) && 'wordpressdotcom' != $handle )
    5595            $og_tags['twitter:creator'] = '@' . $handle;
    5696    }
    5797
     98    // Make sure we have a description for Twitter, their validator isn't happy without some content (single space not valid).
     99    if ( ! isset( $og_tags['og:description'] ) || '' == trim( $og_tags['og:description'] ) ) { // empty( trim( $og_tags['og:description'] ) ) isn't valid php
     100        $has_creator = ( !empty($og_tags['twitter:creator']) && '@wordpressdotcom' != $og_tags['twitter:creator'] ) ? true : false;
     101        if ( 'photo' == $card )
     102            $og_tags['twitter:description'] = ( $has_creator ) ? sprintf( __('Photo post by %s.'), $og_tags['twitter:creator'] ) : __('Photo post.');
     103        else if ( !empty( $extract ) && 'video' == $extract['type'] ) // use $extract['type'] since $card is 'summary' for video posts
     104            $og_tags['twitter:description'] = ( $has_creator ) ? sprintf( __('Video post by %s.'), $og_tags['twitter:creator'] ) : __('Video post.');
     105        else if ( 'gallery' == $card )
     106            $og_tags['twitter:description'] = ( $has_creator ) ? sprintf( __('Gallery post by %s.'), $og_tags['twitter:creator'] ) : __('Gallery post.');
     107        else
     108            $og_tags['twitter:description'] = ( $has_creator ) ? sprintf( __('Blog post by %s.'), $og_tags['twitter:creator'] ) : __('Blog post.');
     109    }
     110
     111    return $og_tags;
     112}
     113
     114function wpcom_twitter_cards_gallery( $extract, $og_tags ) {
     115    foreach( $extract['images'] as $key => $value ) {
     116        if ( $key > 3 )
     117            break; // Can only send a max of 4 picts (https://dev.twitter.com/docs/cards/types/gallery-card)
     118        $og_tags[ 'twitter:image' . $key ] = add_query_arg( 'w', 640, $value['url'] );
     119    }
    58120    return $og_tags;
    59121}
  • jetpack/trunk/modules/publicize/enhanced-open-graph.php

    r803106 r808325  
    1111
    1212    global $post;
    13     $summary = Jetpack_Media_Summary::get( $post->ID );
    1413
    1514    // Don't pick the OG video stuff over a featured image
     
    1817        return $tags;
    1918    }
     19
     20    $summary = Jetpack_Media_Summary::get( $post->ID );
    2021
    2122    if ( 'image' != $summary['type'] )
     
    6364
    6465    global $post;
    65     $summary = Jetpack_Media_Summary::get( $post->ID );
    6666
    6767    // Don't pick the OG video stuff over a featured image
     
    7070        return $tags;
    7171    }
     72
     73    $summary = Jetpack_Media_Summary::get( $post->ID );
    7274
    7375    if ( 'video' != $summary['type'] ) {
Note: See TracChangeset for help on using the changeset viewer.