Feb 03, 2017 in Drupal 8, Modules, Snippets

When using lazy loading of images, I encountered an important issue. Social sharing engines like Facebook can't read placeholder images. 

In this drupal 8 tutorial we'll fix this issue by creating a small custom module handling image tokens. 

First, download and install the Meta tags module. With this module you would normally set the og:image property. Problem is, if we use lazy loading it will share the placeholder image. Follow the instructions below:

Create customtoken.info.yml file 

name: Customtoken
type: module
description: "Returns real url of image to share"
package: Token
core: 8.x

Create customtoken.module file

We will be using a service called Image style, so on top of the file, we include the service:

use Drupal\image\Entity\ImageStyle;

Then we call hook_token_info to define our new token:

/**
 * Implements hook_token_info()
 */

function customtoken_token_info() {
  $type = array(
      'name' => t('Sharing'),
      'description' => t('Tokens used for sharing.'),
      'needs-data' => 'node'
  );

  // Add customtoken for our image
  $node['customtoken_for_sharing'] = array(
      'name' => t("customtoken"),
      'description' => t("The unique url of an image for sharing.")
  );

  return array(
      'types' => array('node' => $type),
      'tokens' => array('node' => $node)
  );
}

This will add the token to the default tokens available for nodes. Now, we have to define what to return when the tokens gets called. In this example we set the token for nodes of type 'blog' and we use the image from 'field_image' with the image style 'large':

/** 
* Implements hook_tokens() 
*/

function customtoken_tokens($type, $tokens, array $data, array $options, \Drupal\Core\Render\BubbleableMetadata $bubbleable_metadata) {
  $token_service = \Drupal::token();

  $replacements = array();

  if ($type == 'node' && !empty($data['node'])) {
    /** @var \Drupal\node\NodeInterface $node */
    $node = $data['node'];

    foreach ($tokens as $name => $original) {
      switch ($name) {
        // Simple key values on the node.
        case 'customtoken':
          $type = $node->getType();
          $url_final = '';
          if($type == 'blog'):
          if(isset($node->get('field_image')->entity)){
          $image_style = 'large'; // Or whatever your image style's machine name is.
          $style = ImageStyle::load($image_style);
          $url_final = $style->buildUrl($node->get('field_image')->entity->getFileUri()); // Generates file url.
          } endif;
          $replacements[$original] = $url_final;
          break;
      }
    }

  }
  return $replacements;
}

Clear cache and head towards the meta tag module. Now the custom token will be available for use. Use a debugging service like Facebook url linter to see check if the image gets shared correctly. Good luck!