im running a blog using the Ghost platform. Ghost is built on Nodejs but I don't know much about it. I have built the following code the grab the first image of every post and set it as og:image. The problem is it loads only after the website arrives in the user's machine. Is it possible to execute this from the server and then send it to the user?
$(document).ready(function() {
var siteURL = location.host;
if(
$('.post-template').length > 0 ||
$('.page-template').length > 0
) {
var featured_image = $('.post-content img[alt="featured-image"]').first().attr('src');
// check if the featured image exists
if(featured_image && featured_image.length > 0) {
var featured_image_fe = featured_image;
// create container for the image
if(featured_image_fe.substr(0,7) != 'http://'){
featured_image_fe = siteURL + featured_image_fe;
}
$('meta[property="og:image"]').attr('content', featured_image_fe);
} else {
var featured_image = $('.post-content img').first().attr('src');
if(featured_image && featured_image.length > 0) {
var featured_image_nfe = featured_image;
if((featured_image_nfe.substr(0,7) != 'http://') && (featured_image_nfe.substr(0,8) != 'https://')){
featured_image_nfe = 'http://' + siteURL + featured_image_nfe;
}
$('meta[property="og:image"]').attr('content', featured_image_nfe);
} else {
$('meta[property="og:image"]').attr('content', 'http://media.techhamlet.com/wp-content/uploads/2014/06/techhamlet.jpg');
}
}
}
}
Yes, this is definitely possible. I have figured out a quick hack to get og:image support working in Ghost. This is definitely a non-optimal solution, but it requires the fewest code changes. You'll need to install cheerio and modify two files.
We need to update the formatResponse function starting on line 76.
var cheerio = require('cheerio');
function formatResponse(post) {
var $ = cheerio.load(post.html);
var firstImage = $('img').first();
if(firstImage) {
post.meta_image = firstImage.attr('src');
}
// Delete email from author for frontend output
// TODO: do this on API level if no context is available
if (post.author) {
delete post.author.email;
}
return {post: post};
}
What we're doing it running the post HTML through cheerio. Grabbing the first image, and stuffing the src into a new variable (meta_image) off of the post object. This will make that variable available to the handlebars templating system.
Here I just updated the {{! Page Meta }} section like so:
{{! Page Meta }}
<title>{{meta_title}}</title>
<meta name="description" content="{{meta_description}}" />
{{#if this.post.meta_image}}
<meta property="og:image" content="{{this.post.meta_image}}" />
{{/if}}
<meta name="HandheldFriendly" content="True" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
We just check to see if this.post.meta_image exists, and if it does create the meta tag.
What you should really do to add this feature is add an additional field to the post object for the og:image. Then you would either populate that with a separate field from the admin, or you could parse the html whenever you save your post and put the value into the appropriate field. This way, the logic for populating the og:image is only run once when the page is saved versus every time the page is displayed.
This was mean as a comment, but is far too long, and I don t know Gosht either
Why do you have
if (
$('.post-template').length > 0 ||
$('.page-template').length > 0
)
? Checking two time the same condition will just slow thing down if anything.
If I understand your goal correctly, you need to load images dynamically, if node.js can access the list of image, you do can generate the html dynamically (with the help of views with express, or jade), with the right html field instead of javascript.
What you can do:
In node js:
var express = require('express'),
app = express();
function execute () {
return 'Html stuff to load the image';
}
app.get('/', function (res, req) {
var html_begin = '<head></head><body>',
html_end = '</body>';
res.send(html_begin + execute() + html_end);
});
So the client get
<head>
</head>
<body>
Html stuff to load the image
</body>
But you can t just say to node.js to execute something in the page before sending it.