The Best Google Add-ons for Docs, Sheets, Slides and Google Forms

The availability of third-party add-ons for Google Docs, Sheets and Google Slides have certainly made the Google Office productivity suite more capable and useful. If you haven’t tried them yet, open any Google document or spreadsheet in your Google Drive and look for the new add-ons menu near Help. G Suite users may have to ask their admin to enable support for add-ons for the organization.

For starters, Google add-ons are like extensions for Chrome. Extensions add new features to the Chrome browser and add-ons extend the functionality of Google Office applications. To give you an example, here’s the screenshot of a Twitter add-on I wrote for Google Docs and Google Sheets that you can use to find and curate tweets right inside your documents.

Twitter Curator is an add-on for Google Docs and Sheets Twitter Curator is an add-on for Google Docs and Sheets

Anyone can write an add-on for Google Docs. All you need are some basic programming skills for writing HTML, CSS for styling the add-on while the server side code is written in Google Apps Script which is similar to JavaScript but runs on the Google Cloud.

Google Apps Script vs Google Add-ons

Google Add-ons are written in the Google Apps Script language but while regular Google Scripts can work on any document in your Google Drive, add-ons only work against the document or sheet that’s currently open in your browser.

Also, while Google Scripts support triggers and can run in the background (like this Website Monitor), add-ons can only run while a document or sheet is open and active. (Update: Google now allows you to create time-based triggers for add-ons)

The other big difference is that you can view the source code of regular Google Scripts while in the case of add-ons, the code is hidden from the end user. This helps developers protect their code but a downside is that the user has no clue about what’s happening behind the scenes.

We have seen issues with Chrome extensions and add-ons for Google Docs can be a target as well. For instance, an add-on can possibly email a copy of the current document or sheet to another email address? Or maybe it can share a folder in Google Drive with someone else. All add-ons currently listed in the Chrome store have been tested and reviewed by Google but if they open the gates for all, I would be a little hesitant to install add-ons created by unknown developers.

The Best Add-ons For Google Docs, Sheets and Google Slides

The GSuite marketplace lists hundreds of Google add-ons and here are some of favorite ones that you should have in your Google Docs and Sheets. The are compatible with both GSuite and consumer Google accounts.

  1. Mail Merge for Gmail - Send personalized emails with emails to multiple email recipients with Mail Merge for Gmail and G Suite.
  2. Document Studio - Generate certificates, invoices, and other documents automatically from source data in Google Sheets or Google Form submissions.
  3. Download Gmail Emails - Download your Gmail messages and attachments in Google Drive for archiving.
  4. Twitter Archiver - Save tweets forever in a Google Sheet for any search term or hashtag.
  5. Email Scheduler for Gmail - Schedule emails inside Gmail for sending later at a specific date and time. Send repetitive emails that go on a recurring schedule.
  6. Google Drive Permissions - Know who has access to your files in Google Drive.
  7. Gmail Address Extractor - The add-on extracts the email addresses from the header and body of email messages for preparing a mailing list.
  8. Google Slides Studio - Convert Google Slides presentations to animated GIF and MP4 movies.
  9. Twitter Curator - Search, filter and add tweets in a Google Documents. It is like Storify for Google Docs.
  10. Google Forms Notifications - Get Google Forms responses in an email message when people submit your forms. Send customized email notifications to respondents.
  11. Email Spreadsheet as PDF - Convert and email Google Spreadsheets as PDF, Excel or CSV to multiple people. Email sheets manually or on a recurring schedule.
  12. Bulk Gmail Forward - Easily forward one or more email threads from Gmail to any other address.
  13. Email AutoResponder for Gmail - Setup email autoresponders in Gmail and quickly reply to messages using pre-written email templates.
  14. HelloFax - You can now send a fax to any number worldwide directly from inside Google documents. The free version lets you fax up to 5 pages.
  15. UberConference - You can have an audio conference with up to 10 people while working on a Google Document. There’s an option to record the call too.
  16. PanDoc - You can send the current document to the client from within Google Docs to request their legally-binding signature.
  17. Unsplash Photos - Instantly search and embed free photos in your Google Slides from the extensive image database.
  18. Avery - Create address labels inside Google Docs for printing.
  19. EasyBib - Cite books, journal articles and websites and add them to your Google Documents in MLA, APA and Chicago style.
  20. Lucidchart - Create flow charts, diagrams, site mockups, org charts and other technical drawings inside your Google Documents.
  21. Mapping Sheets - Create a spreadsheet with a list of places and the sheets add-on will plot them on a Google Map.
  22. TextHelp - This is like the yellow highlighter for your Google Documents. Select and highlight passages and save the annotations in a separate document.

Related tutorial: How to Create a Google Docs Add-on

The Best Online Teachers for Learning Web Development

For the past few months, I have been on a learning spree looking to enhance my existing coding skills and also learn new programming languages and frameworks. In this process, I have watched a countless number of video tutorials and online courses that pertain to programming and, specifically, web development.

In my quest to become a better developer, I’ve come across several awesome “teachers” who aren’t just excellent programmers but awesome educators and have the art of explaining complex and difficult concepts.

Learn Modern Web Programming with the Best Online Teachers

This is an attempt to highlight the best instructors on the Internet for JavaScript, React, Redux, Node.js, Firebase (database and storage), Docker, Google Golang, Typescript, Flutter (for mobile app development), Dart, Git, Webpack and Parcel bundler.

I’ve taken courses by every single instructor mentioned here (PDF) and recommend them highly.

Awesome Web Teachers

Language / PlatformTeacher / Course
React.jsAndrew Mead, Maximilian Schwarzmüller, Stephen Grider, Ryan FlorenceScott Tolinski, Elijah Manor, Brian Holt, Dave CeddiaKirupa Chinnathambi
Advanced JavaScript / ES6 / ES2017Anthony Alicea, Wes Bos, Mark Zamoyta, Tyler McGinnis,  Mosh HamedaniKent C. DoddsKyle SimpsonKyle Robinson YoungBrandon Morelli, Cody Seibert
ReduxDan AbramovShaun PellingBucky RobertsCory House
Dart & FlutterMary Xia & Matt SullivanStephen Grider, Maximilian Schwarzmüller, Filip & Emily Fortuna
Docker / KubernetesJake Wright, Stephen Grider, James Lee
Webpack / Parcel web bundlerAndrew MeadLawrence Whiteside, Sean LarkinPetr TichyBrad TraversyMax Schwarzmüller
Node.jsMaximilian SchwarzmüllerStephen GriderAndrew MeadAzat MardanAnthony AliceaSamer Buna
Git & GithubTrevor MillerAlex Garret-SmithTom Preson-Werner, Daniel Shiffman
Go LanguageTodd McLeod, Stephen Grider, Derek Banas, Jon Calhoun, Harrison Kinsley
TypeScriptTodd MottoJohn LidquistBasarat Ali SyedMarius Schulz
Firebase / FirestoreDavid East, Doug Stevenson, Shaun Pelling, Todd Kerpelman, Steve Kinney
Google Chrome Dev ToolsPaul Irish, Surma, Umar Hansa, Jon Kuperman
GraphQLAndrew Mead, Stephen Grider

Also see: Learn How to Code Online

How to Move Files Uploads from Google Forms to a Specific Folder in Google Drive

The File Upload feature of Google Forms lets you receive files from form respondents directly in your Google Drive. You may add the File Upload question in your Google Form to receive PDF assignments from students, résumé applications, portfolio images from contestants, and so on. When a respondent uploads a file through Google Forms, the file are stored in a fixed folder of your Google Drive. All files are uploaded in the same folder and, thus looking at the file in your Google Drive, it is difficult to determine which respondent has uploaded which set of files. We can however use Google Apps Script with Google Form triggers to instantly organize files in Google Drive as soon as they are uploaded by the form respondent. You can change the destination folder where files are stored or create custom folders based on the form response.

Organiza File Uploads in Google Drive

    In the following example, we will create a parent folder in Google Drive to house all the uploaded files. Each form response will have its own subfolder and all files for that specific form entry will go in the same folder.

Create Parent Folder

To get started, go to your Google Drive and create a new folder (or use an existing folder). Open the folder and grab the ID of the folder from the browser’s address bar as shown in the screenshot.

Add the Google Script

Next, go to your Google Form that is accepting File Uploads and choose Script Editor from the 3-dot menu.   Inside the script editor, remove all the existing code and copy-paste the following snippet. Remember to replace the Folder Id in line #1 with the Id of the folder that you’ve created in the previous step.
const PARENT_FOLDER_ID = "<<Folder ID here>>";

const initialize = () => {
  const form = FormApp.getActiveForm();
  ScriptApp.newTrigger("onFormSubmit").forForm(form).onFormSubmit().create();
};

const onFormSubmit = ({ response } = {}) => {
  try {
    // Get a list of all files uploaded with the response
    const files = response
      .getItemResponses()
      // We are only interested in File Upload type of questions
      .filter(
        (itemResponse) =>
          itemResponse.getItem().getType().toString() === "FILE_UPLOAD"
      )
      .map((itemResponse) => itemResponse.getResponse())
      // The response includes the file ids in an array that we can flatten
      .reduce((a, b) => [...a, ...b], []);

    if (files.length > 0) {
      // Each form response has a unique Id
      const subfolderName = response.getId();
      const parentFolder = DriveApp.getFolderById(PARENT_FOLDER_ID);
      const subfolder = parentFolder.createFolder(subfolderName);
      files.forEach((fileId) => {
        // Move each file into the custom folder
        DriveApp.getFileById(fileId).moveTo(subfolder);
      });
    }
  } catch (f) {
    Logger.log(f);
  }
};
Tip: The script can also be enhanced to create custom folder names based on the user’s answers in the form response.

Create OnFormSubmit Trigger

Inside the script editor, select initialize from the function drop-down and click the Run button to create the OnFormSubmit trigger for your current Google Form. This will essentially run the Apps Script code whenever someone submits a new form entry and upload files to a specific folder in Google Drive.     That’s it. Go to your Google Form and submit a new test entry. You should now see all the uploaded files neatly organized in a custom folder under the parent folder. The name of the custom folder is the unique Response Id that Google Forms automatically assigns to every form submission.   PS: You can combine File Uploads in Google Forms with Document Studio to generate customized PDFs (certificates, employee ID cards, etc) from the uploaded images

How to Send a File to Participants After they Submit your Google Form

When someone fills out your Google Form, you may want to send a file or two to the form respondent. For instance:

  1. A school teacher can send a Word document containing a copy of the answers to students who have completed the quiz.
  2. A musician can send her latest composition as an MP3 file to users who have completed her website survey built with Google Forms.
  3. An author can email a preview copy of her upcoming book in PDF to fans who have subscribed to her newsletter.
  4. An online store may send their catalog PDF to customers who have placed orders through Google Forms.

Demo - Send Files with Google Forms

Open this Google Form, type your email address and hit the Submit button. Check your inbox and you should immediately find a PDF copy of our famous 101 useful websites collection.

How to Attach Files to Form Emails

The Email Notifications add-on for Google Forms lets you send customized emails to form respondents after a new entry is received. The same notification can also be customized to include one or more file attachments that are picked from your Google Drive and sent as an attachment in the auto-responder email.

Add File to Google Drive

  1. Go to the Google Drive website and upload any file that you wish to send via Google Forms.
  2. Change the sharing settings on the file so that it is accessible to anyone with a link. You cannot attach private files to form emails.
  3. Right-click the file in Google Drive and choose Get Link to copy the full URL of the file to the clipboard.

File Attachments in Google Drive

Configure Google Forms

  1. Go to your Google Form, and create a new email rule.
  2. Check the Notify Form Submitter option and select the form field where you ask for the email address of the form submitter.
  3. Go to the Attach Files section and paste the URL of the Google Drive file that you have copied in the previous step.

Save the rule to activate it. Submit a new form and when new users submit the form, they’ll automatically receive a copy of your file as an attachment.

Send File Attachment

PS: You may use this workflow to send files in any format including PDF, Images, Audio, Video, GIFs, PowerPoint, Excel and Word documents. The file size should be less than 5 MB. Also, it is not possible to attach native Google file formats like Google Docs, Sheets and Google Slides.

JavaScript Design Patterns

This article is a summary of the various design patterns in JavaScript that help us create clean, easier to maintain code without polluting the global namespace.

Object Literal Design Pattern

To avoid the possibility of collusion with other variables of the same name in the global namespace, take all your variables and functionn and make them part of an object with a unique name.

var com = com || {};
com.digitalinspiration = com.digitalinspiration || {};
com.digitalinspiration.person = {
  _name: "Amit Agarwal",
  _country: "",
  setCountry: function (country) {
    this._country = country;
  },
  printCountry: function () {
    console.log(this._name + " lives in " + this._country);
  },
};
com.digitalinspiration.person.setCountry("India");
com.digitalinspiration.person.printCountry();

Module Design Pattern

This pattern helps create private variables in JavaScript that cannot be accessed from the global scope as everything is wrapped inside an IIFE. We create a module that returns an object containing all the public functions. The variable are not accessible outside the module.

var personModule = (function () {
  // private variables and methods
  var _name = "Amit Agarwal";
  var _country = "";
  var print = function () {
    console.log(_name + " lives in " + _country);
  };
  return {
    setCountry: function (country) {
      _country = country;
    },
    printCountry: function () {
      console.log("Calling private method to print " + _country);
      print();
    },
  };
})();

personModule.setCountry("India");
personModule.printCountry();

Module Reveal Pattern

The Reveal Module design pattern makes it easy for the private methods and properties to communicate with the public methods. All methods and variables are hidden unless deliberately exposed inside the returning object.

var personModule = (function () {
  var _name = "Amit Agarwal";
  var _interests = [];
  function _printInterests() {
    console.log(_name + " likes " + _interests.join(", "));
  }
  function addInterest(interest) {
    _interests.push(interest);
  }
  function printInterests() {
    console.log("Calling private method");
    _printInterests();
  }
  return {
    printInterests: printInterests,
    addInterest: addInterest,
  };
})();

personModule.addInterest("Travel");
personModule.addInterest("Reading");
personModule.printInterests();

Avoid the Global Scope

Here we conditionally add our module to the global scope and make everyithng private by wrapping our entire module in an IIFE. The advantage with the pattern is that we are not immediately adding elements to the global scope but performing checks to avoid overriding names.

(function (win) {
  var personModule = (function () {
    var _name = "Amit Agarwal";
    function printName() {
      console.log(_name);
    }
    return {
      printName: printName,
    };
  })();
  if (!win.personModule) {
    win.personModule = personModule;
  } else {
    throw new Error("Cannot initialize application");
  }
})(window);

window.personModule.printName();

YouTube Email Alerts – Monitor Videos around your favorite Topics

The Google Alerts service makes it easy for you to monitor brand mentions and your favorite topics on the Internet. Just specify one or more keywords and Google will send an email notification when new web pages matching your search keywords are found on the web.

The YouTube Email Alerts service is similar to Google Alerts but instead of scanning the whole worldwide web, it limits the searches to videos uploaded on the YouTube website. It then sends automatic email notifications when new videos are uploaded on YouTube around your topics of interest.

Here’s a sample email notification sent by the YouTube Alert system that, in this example, is configured to track new video uploads around three topics - Tesla Model Y, The Queen’s Gambit, and Minecraft tutorials.

YouTube Email Alerts

Setup YouTube Email Alerts

Here’s a step by step guide on how to set up your own YouTube email alert system for monitoring videos around your topics of interest.

  1. Click here to make a copy of the YouTube alert script in your Google Account.

  2. Inside the Google Script, go to line #12 and update the default configuration. You need to specify the email address where the alerts should arrive, the topic or keywords that you wish to track, and the list of negative words. If a matching video contains any of the negative words, they’ll be filtered out of the email notification.

  3. Go to the Run menu and choose the initialize option. Authorize the Google Script and your email system is deployed instantly. Go to your Gmail sent items and you should see an email alert with the matching videos.

The system is now deployed and it will send one email digest per day with a list of matching videos. The email is sent around 11 AM GMT but you can change this time by updating the value of the emailAlertHour property in the configuration.

Configure Video Alerts

How YouTube Email Alerts Work

The alert system is built using the official YouTube API with Google Apps Script. You can find the complete source code on Github.

When you run the initialize function, it creates a cron job that will automatically run once per day around the specified hour. It then uses the YouTube API to find all matching videos that have been uploaded on YouTube since the last execution of the script. It takes the 10 most relevant videos and adds them to the notification email.

const fetchYouTubeVideos = (query = "cats") => {
  const date = new Date();
  date.setDate(date.getDate() - 3);
  const dateFormat = "yyyy-MM-dd'T'HH:mm:ss'Z'";
  const publishedAfter = Utilities.formatDate(date, "UTC", dateFormat);
  const { items = [] } = YouTube.Search.list(["snippet"], {
    maxResults: 10,
    regionCode: "US",
    publishedAfter: publishedAfter,
    relevanceLanguage: "en",
    q: query,
    type: ["video"],
    fields: "items(id(videoId),snippet(title, channelTitle, channelId))",
  });
  return items.map((item) => {
    const {
      id: { videoId },
      snippet: { title, channelTitle, channelId },
    } = item;
    return { videoId, title, channelTitle, channelId };
  });
};

The preferredLanguage parameter in the configuration is, by default, set to en (English) and instructs YouTube to return videos that are most relevant to the specified language. You can use your two-letter language ISO code (like fr from French or hi for Hindi) here.

Similarly, the regionCode parameter (default is US) helps you restrict search results to videos that can be viewed in your country.

Also see: Google Drive File Monitor

How to Share User Properties between Google Apps Script Projects

The Properties Service of Google Apps Script is used by developers to store app configuration and user specific settings. The properties data is scoped to a specific user, or a specific project, and cannot be shared between different projects.

The Email Form Notifications add-on also uses the Properties Service to store rules that are defined by the user. The rules created by User A are not accessible to User B.

However, in some specific cases, we may want to give access to our store data to another user so they may build upon the existing configuration rather than having to build everything from scratch.

The new import export option allows the user to export properties data as a plain text file that can be imported into the property store of another user.

Access the Property Store

On the server side (Google Script), we define two methods - one for exporting data as a JSON file and the other method for importing data from the property store of another user into our own.

/* Choose DocProperties for editor add-ons */
const getStore = () => {
  return PropertiesService.getUserProperties();
};

/* Export user settings */
const exportUserData = () => {
  const data = getStore().getProperties();
  return JSON.stringify(data);
};

/* Import user settings */
const importUserData = (data) => {
  const json = JSON.parse(data);
  getStore().setProperties(json);
  return 'OK';
};

Export User Properties as a Text File

For exporting data, the HTML file contains a simple download button that connects to the server, fetches the data and allows the user to save this data as a text file on their computer.

<p>Export Data</p>
<button onclick="downloadFile();return false;" href="#">Export</button>

<script>
  function downloadFile() {
    google.script
      .withSuccessHandler(function (data) {
        var a = document.createElement('a');
        var blob = new Blob([data], {
          type: 'text/plain',
        });
        var url = URL.createObjectURL(blob);
        a.setAttribute('href', url);
        a.setAttribute('download', 'file.txt');
        a.click();
      })
      .exportUserData();
  }
</script>

Import User Properties from a Text File

For importing data into the property store, the user can upload a text (JSON) file that contains data as key-value pairs. These files are easily readable in any text editor and you can also add define new properties by adding new keys to the JSON file.

<p>Import data</p>
<input type="file" id="file" accept="text/plain" />

<script>
  document.getElementById('file').addEventListener(
    'change',
    function (event) {
      var file = event.target.files[0];
      if (file.type !== 'text/plain') {
        window.alert('Unsupported file');
        return;
      }
      var reader = new FileReader();
      reader.onload = function (e) {
        google.script.run
          .withSuccessHandler(function (success) {
            window.alert(success);
          })
          .withFailureHandler(function (err) {
            window.alert(err);
          })
          .importUserData(e.target.result);
      };
      reader.readAsText(file);
    },
    false
  );
</script>

The File Reader API of JavaScript is used to read the contents of the selected text file. The onload event gets fired when the file has been successfully read in memory.

The readAsText method of File Reader will read the file as a string but you may also use the readAsDataURL method should be wish to upload file in base64 encoded format that can be decoded on the server.

Useful JavaScript Functions

The code snippets are from a JavaScript course on Udemy.

  1. Create a function that can be invoked only once.
const once = (fn, ...args) => {
  let called = false;
  return () => {
    if (called === false) {
      called = true;
      return fn(...args);
    }
    return 'Cannot call again';
  };
};

const printName = (text, time) => console.log(`${text} at ${time}`);
const fn = once(printName, 'Google', new Date().toString());

console.log(fn());
console.log(fn());
  1. Measure the time it takes for a JavaScript function to run.
const getUserData = async (user) => {
  const response = await fetch(`https://api.github.com/users/${user}`);
  const json = await response.json();
  return json;
};

const time = (fn, ...args) => {
  console.time('time');
  const result = fn(...args);
  console.timeEnd('time');
  return result;
};

time(() => getUserData('labnol'));
  1. A debounce function that delays invocation until a certain amount of time has passed since the last time that debounce function was invoked.
const debounce = (fn, waitInMs) => {
  let debounced = false;
  return (...args) => {
    if (debounced) clearTimeout(debounced);
    debounced = setTimeout(() => fn(...args), waitInMs);
  };
};

const getWindowLayout = (event) => {
  console.log(event, window.innerHeight, window.innerWidth);
};

window.addEventListener('resize', debounce(getWindowLayout, 500));

How to Create JSON Web Token (JWT) with Google Apps Script

You can use Google Script to create JSON Web Tokens (JWT) that can be provided to secure routes so that only authenticated requests that contain a valid token can connect to the APIs (e.g., the Zoom API).

All JSON Web Tokens have three parts:

  1. The header that specifies the hash algorithm that is used for signing and decrypting the JWT.
  2. The payload in JSON format that contains all the user data. The iat and exp properties represent the issue date and the expiration time respectively but you can pass any data to the payload.
  3. The signature data that allows APIs to establish the authenticity of the access token.

The parts are joined with a dot (period) and data is encoded in Base64 using the Utilities.base64EncodeWebSafe method of Apps Script.

Create JSON Web Token

const createJwt = ({ privateKey, expiresInHours, data = {} }) => {
  // Sign token using HMAC with SHA-256 algorithm
  const header = {
    alg: 'HS256',
    typ: 'JWT',
  };

  const now = Date.now();
  const expires = new Date(now);
  expires.setHours(expires.getHours() + expiresInHours);

  // iat = issued time, exp = expiration time
  const payload = {
    exp: Math.round(expires.getTime() / 1000),
    iat: Math.round(now / 1000),
  };

  // add user payload
  Object.keys(data).forEach(function (key) {
    payload[key] = data[key];
  });

  const base64Encode = (text, json = true) => {
    const data = json ? JSON.stringify(text) : text;
    return Utilities.base64EncodeWebSafe(data).replace(/=+$/, '');
  };

  const toSign = `${base64Encode(header)}.${base64Encode(payload)}`;
  const signatureBytes = Utilities.computeHmacSha256Signature(
    toSign,
    privateKey
  );
  const signature = base64Encode(signatureBytes, false);
  return `${toSign}.${signature}`;
};

Generate Token with your Private Key & Payload

const generateAccessToken = () => {
  // Your super secret private key
  const privateKey =
    'ZPYu33tz8QYU3hwJQXgHpZsKfYn0r2poopBx7x1n3rmeIvuGU4wf65kk6rV1DrN';
  const accessToken = createJwt({
    privateKey,
    expiresInHours: 6, // expires in 6 hours
    data: {
      iss: Session.getActiveUser().getEmail(),
      userId: 123,
      name: 'Amit Agarwal',
    },
  });
  Logger.log(accessToken);
};

You can paste the generated access token in jwt.io and you’ll be able to see the content (payload) of the decoded token. Please note that if the token has invalid signature data, the payload may still be decoded as it is encoded in Base64.

JSON Web Token with Google Apps Script

Decoding JWT Payload with Google Apps Script

const parseJwt = (jsonWebToken, privateKey) => {
  const [header, payload, signature] = jsonWebToken.split('.');
  const signatureBytes = Utilities.computeHmacSha256Signature(
    `${header}.${payload}`,
    privateKey
  );
  const validSignature = Utilities.base64EncodeWebSafe(signatureBytes);
  if (signature === validSignature.replace(/=+$/, '')) {
    const blob = Utilities.newBlob(
      Utilities.base64Decode(payload)
    ).getDataAsString();
    const { exp, ...data } = JSON.parse(blob);
    if (new Date(exp * 1000) < new Date()) {
      throw new Error('The token has expired');
    }
    Logger.log(data);
  } else {
    Logger.log('🔴', 'Invalid Signature');
  }
};

If you are new to JWT, the video tutorials by Kyle Cook here and here are a good place to start.

Lite YouTube Embeds – A Better Method for Embedding YouTube Videos on your Website

It is easy to embed a YouTube video but you’ll be surprised to know how much extra weight a single YouTube video embed can add to your web pages. The browser has to download ~800 kB of data (see screenshot) for rendering the YouTube video player alone. And these files are downloaded even before the visitor has clicked the play button.

Embed YouTube Video Player Size

The embedded YouTube video not only increases the byte size of your web pages but the browser has to make multiple HTTP requests to render the video player. This increases the overall loading time of your page thus affecting the page speed and the core vitals score of your website.

The other drawback with the default YouTube embed code is that it renders a video player of fixed dimensions and isn’t responsive. If people view your website on a mobile phone, the video player may not resize properly for the small screen.

Embed YouTube Videos without Increasing Page Size

The now defunct Google+ employed a very clever technique for embedding YouTube videos. When the page was initially loaded, Google+ would only embed the thumbnail image of the YouTube video and the actual video player was loaded only when the user clicked inside thumbnail.

The thumbnail frame image of YouTube videos are about 15 kB in size so we are able to reduce the size of web pages by almost an MB.

Lite YouTube Embed Demo

Open this demo page to view the Google+ technique in action. The first video the page is embedded using the default IFRAME code while the second video uses the lite mode that loads the YouTube video on demand only.

When a user clicks the play button, the thumbnail image is replaced with the standard YouTube video player with autoplay set to 1 so the video would play almost instantly. The big advantage is that the extra YouTube JavaScript gets loaded only when someone decides to watch the embedded video and not otherwise.

Light and Responsive YouTube Embeds

The standard embed code for YouTube uses the IFRAME tag where the width and height of the video player are fixed thus making the player non-responsive.

The new on-demand embed code for YouTube is responsive that adjusts the player dimensions automatically based on the screen size of the visitor.

YouTube Embed Code

Embed YouTube Videos Responsively - Tutorial

Step 1: Copy-paste the following HTML snippet anywhere in your web page where you would like the YouTube video to appear. Remember to replace VIDEO_ID with the actual ID of your YouTube video.

<div class="youtube-player" data-id="VIDEO_ID"></div>

We will not assign height and width since the video player will automatically occupy the width of the parent while the height is auto-calculated. You can also paste multiple DIV blocks with different video IDs if you need to embed multiple YouTube videos on the same page.

Step 2: Copy-paste the JavaScript anywhere in your web template. The script finds all embedded videos on a web page and then replaces the DIV elements with the video thumbnails and a play button (see demo).

<script>
  /*
   * Light YouTube Embeds by @labnol
   * Credit: https://www.labnol.org/
   */

  function labnolIframe(div) {
    var iframe = document.createElement('iframe');
    iframe.setAttribute(
      'src',
      'https://www.youtube.com/embed/' + div.dataset.id + '?autoplay=1&rel=0'
    );
    iframe.setAttribute('frameborder', '0');
    iframe.setAttribute('allowfullscreen', '1');
    iframe.setAttribute(
      'allow',
      'accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture'
    );
    div.parentNode.replaceChild(iframe, div);
  }

  function initYouTubeVideos() {
    var playerElements = document.getElementsByClassName('youtube-player');
    for (var n = 0; n < playerElements.length; n++) {
      var videoId = playerElements[n].dataset.id;
      var div = document.createElement('div');
      div.setAttribute('data-id', videoId);
      var thumbNode = document.createElement('img');
      thumbNode.src = '//i.ytimg.com/vi/ID/hqdefault.jpg'.replace(
        'ID',
        videoId
      );
      div.appendChild(thumbNode);
      var playButton = document.createElement('div');
      playButton.setAttribute('class', 'play');
      div.appendChild(playButton);
      div.onclick = function () {
        labnolIframe(this);
      };
      playerElements[n].appendChild(div);
    }
  }

  document.addEventListener('DOMContentLoaded', initYouTubeVideos);
</script>

Step 3: Copy-paste the CSS before the closing head tag of your web template.

<style>
  .youtube-player {
    position: relative;
    padding-bottom: 56.25%;
    height: 0;
    overflow: hidden;
    max-width: 100%;
    background: #000;
    margin: 5px;
  }

  .youtube-player iframe {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    z-index: 100;
    background: transparent;
  }

  .youtube-player img {
    object-fit: cover;
    display: block;
    left: 0;
    bottom: 0;
    margin: auto;
    max-width: 100%;
    width: 100%;
    position: absolute;
    right: 0;
    top: 0;
    border: none;
    height: auto;
    cursor: pointer;
    -webkit-transition: 0.4s all;
    -moz-transition: 0.4s all;
    transition: 0.4s all;
  }

  .youtube-player img:hover {
    -webkit-filter: brightness(75%);
  }

  .youtube-player .play {
    height: 72px;
    width: 72px;
    left: 50%;
    top: 50%;
    margin-left: -36px;
    margin-top: -36px;
    position: absolute;
    background: url('//i.imgur.com/TxzC70f.png') no-repeat;
    cursor: pointer;
  }
</style>

You can view the light YouTube embed technique in action on this Codepen page.

Please do note that Chrome and Safari browsers on iPhone and Android only allow playback of HTML5 video when initiated by a user interaction. They block embedded media from automatic playback to prevent unsolicited downloads over cellular networks.

YouTube Embed Tutorials

  1. Embed a YouTube Video with Sound Muted
  2. Place YouTube Video as your Webpage Background
  3. Embed Just a Portion of a YouTube Video