VueJS and Facebook share (quick and dirty)

Zoran Perin

It is not secret that Single Page Applications have issue with SEO. Although Google and Facebook claim that their robots are perfectly fit to crawl and inspect you app, reality is somewhat different.

Take for example simple VueJS application. Let say that you have few pages and every page have it is own title and meta tags (OG tags) that is needed for sharing. This is easily solved with great vue-meta plugin and it works pretty fine. Users will have nice page title and if you inspect yout page wou will see how meta tags are changed when you browser different pages. All good!


If you try to share your page, let say you expect to see same page title and meta tags as you would see in browser. Bummer!

Facebook won’t take your pretty meta tags for certain page and display it. Why?! Well, that just doesn’t happen because crawler actually can’t trigger your JS app — so everything that vue-router and vue-meta did for you will (in app) not apply for Facebook crawler.

So, you start to panic, curse and google for answer.

One answer you will find is SSR or Server Side Rendering, as well as prerendering, and that’s pretty fine. But that means that you need to work more on your app, to have X number of generated static pages, etc.

I had same issue recently and here’s the solution I discover that saved me. The solution I will provide will work on PHP and Apache but I believe that this concept can be used easily on Nginx, NodeJS, etc.

We want to trick certain agents, in this case Facebook, Twitter, Pinterest, etc. So, first thing is that we want to detect them. It can be easily done with .htaccess with just one line of code:

RewriteCond %{HTTP_USER_AGENT} (facebookexternalhit/[0–9]|Twitterbot|Pinterest|Google.*snippet)|Slackbot

You see, our .htaccess rule will detect Facebook, Twitter, Pinterest, Google and Slack bots. After the agent is detected, we will trick it to go on PHP page where it will be served with fake data.

RewriteRule ^products/(.*)$$1 [NC,L]

As you can assume, our static.php page will do the rest of the trick with faking meta tags so Facebook will read exactly what you want. So, here’s the static.php:

<?php$product = filter_var($_REQUEST[‘product’], FILTER_SANITIZE_STRING);
$product = str_replace(‘/’, ‘’, $product);
$json = file_get_contents(‘'.$product);
$data = json_decode($json, true);
return makePage($data);function makePage($data) {$page = "".$data['product'];
$html = '<!doctype html>'.PHP_EOL;
$html .= '<html>'.PHP_EOL;
$html .= '<head>'.PHP_EOL;
$html .= '<meta property="og:ur"” content="'.$data['product'].'" />'.PHP_EOL;
$html .= '<meta property="og:title" content="'.$data['title'].'"/>’.PHP_EOL;
$html .= '<meta property="og:description" content="Some description goes here" />'.PHP_EOL;
$html .= '<meta property="og:image" content="'.$data['image'].'.jpg" />'.PHP_EOL;
$html .= '<meta property="og:type" content="website" />'.PHP_EOL;
$html .= '<meta property="og:site_name" content="My Site" />'.PHP_EOL;
$html .= '<meta http-equiv="refresh" content="0;url='.$page.'">'.PHP_EOL;
$html .= '</head>'.PHP_EOL;
$html .= '<body></body>'.PHP_EOL;
$html .= '</html>';
echo $html;

Pay attention to this line:

$html .= '<meta http-equiv="refresh" content="0;url=".$page.'">'.PHP_EOL;

It is needed to trick Facebook agent that URL that is shared is the “real” URL, not the one you just told it to use :)

This solution may not be the prettiest around and I’m aware that on more complex or bigger project I wouldn’t probably use it — I would look at SSR probably), but I think it can be enough for a for small application.

Enjoy coding!

Zoran Perin

Written by

Front-end Web Developer. Firm on Sass, JS and 6-strings. Wannabe nihilist.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade