imgnx
imgnx

Reputation: 789

How do I set the content of a <meta> tag from Node or Express?

I'm building a search engine for a real estate company called Signature REP. I'm trying to use Facebook's Open Graph API following the Sharing for Webmaster's guide and what I'm trying to do is get this image for this website to show up as the image in the post made by the Facebook Sharer.

The problem is that I can't use client-side JavaScript to set the <meta> tag before Facebook's WebCrawler gets to it. I end up with this image (which is the default image for my entire app) instead of this image of the listing (which is what I want).

My server configuration looks like this:

server.js

var express = require("express");
var bodyParser = require("body-parser");
var app = express();
const request = require('request');

// … a bunch of code for webhooks

app.use("/", express.static(__dirname));
app.use("/search", express.static(__dirname));
app.use("/search/:value", express.static(__dirname));
app.use("/search/:value/:id", express.static(__dirname));
app.use("/search/:value/:id/carousel", express.static(__dirname));
app.use("/moreinfo", express.static(__dirname));
app.use("/watchlist", express.static(__dirname));
app.use("*", function(req, res){
    res.status(404).send(`
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" integrity="sha384-WskhaSGFgHYWDcbwN70/dfYBj47jz9qbsMId/iRN3ewGhXQFZCSftd1LZCfmhktB" crossorigin="anonymous">
      <div class="text-center my-5">
        <h1>404</h1>
        <p>Sorry, we cannot find that!</p>
        <a href="https://signaturerep.com/">
          <img src="./404.jpg" />
        </a>
      </div>
    `);
});
app.listen(PORT, () => {
    console.log("Started listening on port", PORT);
});

My index.html page looks like this:

index.html

<!DOCTYPE html>
<html class="no-js" xmlns:fb="http://ogp.me/ns/fb#">
  <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# business: http://ogp.me/ns/business#">

    <!-- Facebook metadata -->
    <meta property="fb:app_id" content="507466823022210" />
    <meta property="og:type" content="business.business" />
    <meta property="og:title" content="&#128205; Signature REP" />
    <meta property="og:description" content="Signature Real Estate Professionals is the Southeast's premiere real estate agency. We provide our clients with the best service up front. From buying and selling homes, to rentals and more, we have all of your real estate needs covered." />
    <meta property="og:image" content="https://cloudbackr.com/volume-nyc1-02/assets/Search.jpg" />
    <meta property="og:url" content="https://signaturerep.com" />
    <meta property="business:contact_data:street_address" content="1425 Market Blvd" /> 
    <meta property="business:contact_data:locality"       content="Roswell, Georgia" /> 
    <meta property="business:contact_data:postal_code"    content="30097" /> 
    <meta property="business:contact_data:country_name"   content="United States" /> 
    <meta property="place:location:latitude"              content="34.0181013" /> 
    <meta property="place:location:longitude"             content="-84.3206112" /> 
  </head>
  <body>
    <div id="fb-root"></div>

    <div id="app"></div>
  </body>
</html>

So, how can I change the HTML header (specifically the content of the meta tag with property=og:image) before the Facebook WebCrawler gets to it? Facebook simply makes a quick GET request to the URL, so setting the meta tag with Express before the app renders should work just fine. I imagine either Node or Express could do this somehow.

All I need to do is send this tag to the Facebook Crawler: <meta property="og:image" content="https://cloudbackr.com/volume-nyc1-02/large-photos/large-52009687-0.jpeg" /> and hope that it picks that tag up instead of the one on index.html (served statically). BUT I also need to do this for the other 4000 listings that I receive every day.

Resources:

Facebook Sharing Debugger

Upvotes: 2

Views: 9723

Answers (1)

Cristiano
Cristiano

Reputation: 556

Use a template engine like Mustache Express. With this extension, you can easily customize your HTML response. About your specific issue, you can:

var mustacheExpress = require('mustache-express');

    // Register '.mustache' extension with The Mustache Express
    app.engine('mustache', mustacheExpress());

    app.set('view engine', 'mustache');
    app.set('views', __dirname + '/views');

Inside view directory put a index.mustache file.

index.mustache

<!DOCTYPE html>
<html class="no-js" xmlns:fb="http://ogp.me/ns/fb#">
  <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# business: http://ogp.me/ns/business#">

    <!-- Facebook metadata -->
    <meta property="fb:app_id" content="507466823022210" />
    <meta property="og:type" content="business.business" />
    <meta property="og:title" content="&#128205; Signature REP" />
    <meta property="og:description" content="Signature Real Estate Professionals is the Southeast's premiere real estate agency. We provide our clients with the best service up front. From buying and selling homes, to rentals and more, we have all of your real estate needs covered." />
    <meta property="og:image" content="{{imageUrl}}" />
    <meta property="og:url" content="https://signaturerep.com" />
    <meta property="business:contact_data:street_address" content="1425 Market Blvd" 
     /> 
    <meta property="business:contact_data:locality"       content="Roswell, Georgia" 
     /> 
    <meta property="business:contact_data:postal_code"    content="30097" /> 
    <meta property="business:contact_data:country_name"   content="United States" /> 
    <meta property="place:location:latitude"              content="34.0181013" /> 
    <meta property="place:location:longitude"             content="-84.3206112" /> 
  </head>
  <body>
    <div id="fb-root"></div>

    <div id="app"></div>
  </body>
</html>

Notice the {{imageUrl}} tag in the content attribute of the meta header with the name og:image.

Finally, register an express route that renders the file:

app.get('/index', function (req, res) {
  let yourImage = getYourImageUrl()
  res.render('index', { imageUrl: yourImage })
})

Sources:

Upvotes: 2

Related Questions