How to Create Dynamic Open Graph Images with Google Sheets


Generate dynamic Open Graph images for your website with Google Sheets without using Puppeteer. All pages on your website can have their own unique Open Graph images created from a Google Slides template.

An open graphic image (OG image) is the image that displays when one of your website’s links is shared on Facebook, LinkedIn, or Twitter. You can provide the image’s public URL in your website’s meta tags and the social media website will take care of it automatically.

  <title>Digital Inspirationtitle>
  <meta property="og:image" content="" />

Open graphic images with Puppeteer

GithubGenericName internally use Google’s Puppeteer library to generate dynamic Open Graph images. Images are generated on the fly by introducing custom HTML code into Puppeteer which generates a screenshot. You can see a sample OG image generated by Github in this Tweeter.

Vercel, the company behind Next.js, also uses Puppeteer for its open graph image builder. Headless chrome is used to render an HTML page, a screenshot of the page is captured, and the file is cached for improved performance.

Create Open Graph images without a puppeteer

Puppeteer is a wonderful library (I use it internally for but it requires some technical know-how to deploy Puppeteer as a cloud feature. Deploying Puppeteer on the cloud also incurs costs, as you have to pay for each request made to the service.

If you’re looking for a no-code, no-cost, no-puppeteer solution, you can use Google Sheets to generate Open Graph images. This is what I use to generate dynamic and unique images for each page of my website. You can see a sample OG image in this Tweeter.

The idea is inspired by Document Studio. You create an image design in Google Slides, replace the placeholder text in the template with your web page title, then generate a screenshot of the presentation and save it to your Google Drive.

To start, make a copy of this Google sheet in your Google Drive. Replace the titles in column A with your page titles and delete the Image URL column. Click it Play authorize the script and you will notice that the spreadsheet is immediately updated with the image URLs for each page.

Add more page titles in google spreadsheet, tap the Play again and the spreadsheet will be updated with the image URLs of the new pages only. That’s it.

Open graphic images

Test your Open Graph images

After adding the Open Graph meta tags to your website, you can test your Open Graph images using the tool below.

  1. – Paste your website URL in the URL field and click on the Validate to see if Twitter is able to render the provided image in your Open Graph meta tags. You can also use this validation tool to clear OG image from twitter cache for any page.

  2. – Paste your website URL in the URL field and click on the Debug to see if Facebook is able to render the provided image in your Open Graph meta tags.

  3. – LinkedIn’s Post Inspector tool can help you determine how your web page will appear when shared on the LinkedIn platform. You can also ask LinkedIn to re-scrape the page if the associated OG image has changed.

How does the Open Graph image generator work?

In Google Sheet, go to the Extensions menu and choose Apps Script to view the source code used to generate the Open Graph images. You can also create graphics in Canva using one of the available templates and then import Canva designs into Google Slides.

The application is written in Google Apps Script. It reads post titles from Google Sheets, generates a copy of the presentation for each line in the sheet, generates a screenshot of the slide, and adds it to your Google Drive.

const FOLDER = 'Open Graph Images';
const TEMPLATE_ID = '1QZ4mR6B36XEVyzJf-s8vq88SDnSRPiRDchJ71VM-cfU';

const APP = {
  getFolder() {
    if (typeof this.folder === 'undefined') {
      const folders = DriveApp.getFoldersByName(FOLDER);
      this.folder = folders.hasNext() ? : DriveApp.createFolder(FOLDER);
    return this.folder;

  getImageUrl(contentUrl, title) {
    const blob = UrlFetchApp.fetch(contentUrl).getBlob();
    const file = this.folder.createFile(blob);
    return file.getUrl();

  getTemplate(title) {
    const slideTemplate = DriveApp.getFileById(TEMPLATE_ID);
    const slideCopy = slideTemplate.makeCopy(title, this.getFolder());
    return slideCopy.getId();

  getThumbnailUrl(presentationId) {
    const { slides: [{ objectId }] = {} } = Slides.Presentations.get(presentationId, {
      fields: 'slides/objectId',

    const data = Slides.Presentations.Pages.getThumbnail(presentationId, objectId);
    return data.contentUrl;

  createImage(title) {
    const presentationId = this.getTemplate(title);
        requests: [
            replaceAllText: {
              containsText: { matchCase: false, text: '{{Title}}' },
              replaceText: title,
    const contentUrl = this.getThumbnailUrl(presentationId);
    const imageUrl = this.getImageUrl(contentUrl, title);
    return imageUrl;

  toast(title) {
    SpreadsheetApp.getActiveSpreadsheet().toast('✔️ ' + title);

  run() {
    const sheet = SpreadsheetApp.getActiveSheet();
      .forEach(([title, url], index) => {
        if (title && !/^http/.test(url) && index > 0) {
          const imageUrl = this.createImage(title);
          sheet.getRange(index + 1, 2).setValue(imageUrl);


Comments are closed.