[Solved] Inject HTML meta tags on the server

I am tinkering with this image storage application, and the last hurdle is to have the proper meta tags in the header so when someone sends the URL via iOS Messages it shows the proper thumbnail, but I am failing at injecting the proper <meta> tags on the server side, because

The machinery that creates link previews will not follow redirects, nor run JavaScript, so metadata must be available on the page without either occurring.Server - side redirects are followed, however, and are a good alternative.
so far I have experimented with WebApp.connectionHandlers, but whatever I inject never makes it to the client, the headers are always just what’s in the client.html

Has anybody figured out how to inject HTML headers on the server?

I think I have been confusing HTTP headers and meta tags, which are part of the downloaded payload.

I guess what I am trying to do can’t be done without full fledged server-rendering …

Hi @jamgold,

Im not sure if you are looking to inject a meta tag but we are doing it with server-rendersink, like the following.

import { onPageLoad } from 'meteor/server-render';


onPageLoad((sink) => {
  // You can get the url data with: sink.request.url.path ...

  sing.appendToHead(`<meta property="og:image" content="${YOUR_VALUE}"/>`);
});

Hope this helps.

2 Likes

I believe I have figured it out. With the help of the server-render package. I added this to the server side, and voila

import { onPageLoad } from "meteor/server-render";

onPageLoad(sink => {
  // parse the request URL
  const path = sink.request.url.path.split('/');
  if(path.length>2 && path[1] == 'image') {
    // only  if we request an image, get the image id
    const id = path[2];
    if (id) {
      const img = DBImages.findOne(id);
      if (img) {
        // append the appropriate meta tags
        sink.appendToHead(` <meta property="og:title" content="${img.name}"/>\n`);
        sink.appendToHead(` <meta property="og:type" content="${img.type}" />\n`);
        sink.appendToHead(` <meta property="og:url" content="https://images.buzzledom.com/image/${id}" />\n`);
        sink.appendToHead(` <meta property="og:image" content="https://images.buzzledom.com/thumbnail/${id}" />\n`);
      }
    }
  }
});

And this is with Blaze

1 Like

@pmogollon that totally (would have) helped, but I figured it out. Our posts properly overlapped :slight_smile:

1 Like

We just went thru this exact issue and ended up using an alternate solution - if you’re interested, we used prerender.io (you can even self host it on the same server if you want). We set it up on it’s own small server so any other future app we build can just re-use it quite easily. It’s nice because it automatically takes care of checking if the request is coming from a crawler type bot (iOS, facebook, whatsapp, etc etc). Happy to post more info/example config (including with redis for caching) if wanted!

Thank you @adammoisa for reminding me of prerender.io. I used to have it setup for an older, much larger project and back then I didn’t understand neither Meteor, nor prerender well enough, so “some things that should not have been forgotten were lost. History became legend. Legend became myth…” you know the rest.

Since this topic started out with a misguided use of WebApp.connectionHandlers, I feel the need to re-habilitate this most awesome feature of the stack by linking to this post which explains how I used it to dynamically serve static files.