Get Email Alerts When COVID-19 Vaccines Become Available Near You

India is currently in the midst of a second wave of the Coronavirus and this one is far more devastating than what we have seen last year. The country is reporting close to 400,000+ new cases every day but the actual count of daily infections could be much higher.

The COVID-19 vaccination program in India was earlier available to people above 45 years of age but starting today (May 1), anyone above the age of 18 years is eligible for Covid-19 vaccination.

Vaccine Availability

COVID-19 Vaccines Near Me

The government’s official website - - has a useful search section that allows you see the nearby vaccination centers in your city or zip code. You’ll also know how many vaccine doses are available at a specific center and the earliest date when the next batch of vaccine stocks are due.

Based on this public data, I have developed an open-source vaccine tracker that will monitor the vaccine availability near you and will send email alerts as stocks become available. The source code of the project is available on Github.

Build your own Covid-19 Vaccine Tracker

Step 1: To get started, click here to make a copy of the Vaccine Tracker Google Sheet in your Google Drive.

Step 2: Click the Vaccine Tracker menu (near the Help menu) and choose Enable as shown in the screenshot.

Vaccine Tracker Google Sheet

Step 3: You may see an authorization window. If you get an “unverified app” message, click the Advanced link and choose “Go to Vaccine Alerts”. The app is 100% safe and open-source.

Step 4: Go to Step 2 now and choose the Enable menu again to launch the tracker. Enter one more pin codes, the email address where you wish to receive the alerts and the age group for which you need to monitor vaccine availability.

Click the Create Email Alert button and your system is up and running. Google Sheets will run this monitor every day and send an email at 8 am indicating the availability of vaccines in your specified areas.

Here’s a copy of the email sent by the vaccine tracker.

Email Alert - Vaccine Tracker

And if you ever wish to stop Google Sheets from tracking vaccine availability, go to the same sheet and choose Disable from the menu.

How to Print the Function Call Flow with Stack Trace in JavaScript

The printStackTrace method of Java is useful for handling exceptions and errors during development. It tells you the exact line number in your source code and the file name where the problem occurred.

If you are working in the JavaScript / Google Apps Script world, you can use the console.trace() method to output the complete stack inside the web console ( or StackDriver logs for Google Scripts).

A better alternative is that you parse the stack property of the Error object. This contains the entire stack trace along with line numbers, column position and the function names.

function printStackTrace() {
  const error = new Error();
  const stack = error.stack
    .map((line) => line.replace(/\s+at\s+/, ""))

function three() {
  console.log("Function Three!");

function two() {
  console.log("Function Two!");

function one() {
  console.log("Function One!");


The output of the printStackTrace method looks something like this. The first few lines are the program output and as you move downwards, you’ll see a list of methods which invoked the previous method.

Function One!
index.js:16 Function Two!
index.js:11 Function Three!
index.js:7 three (index.js:12:3)
two (index.js:17:3)
one (index.js:22:3)

You can use the stack trace to know the exact location of the problematic code in your JavaScript app or if you simply want to print the function calling flow of your JavaScript program without even throwing an exception.

How to Perform IP Address Lookup with Google Sheets

Websites can determine the visitor’s geographic location using their IP address and serve more relevant content. For example, a weather website may use your IP address to estimate your approximate location and provide weather forecast for your current city automatically. A currency exchange website can determine your default currency based on your country which is detected from your IP address.

Google Sheets - IP 2 Location

There are free web IP lookup services, for example, that will reveal the country of your client’s IP address with a simple HTTP request. We internally use that service at Digital Inspiration to determine the payment service provider on the checkout page.

Bulk IP Lookup with Google Sheets

IP2Location is another good alternative that retrieves more detailed geolocation information for any IP address. The IP location lookup service can retrieve the client’s country, city name, region, the ISP name and more.

If you have a bulk list of IP addresses, you can use Google Sheets to estimate the corresponding geographic details for each of the addresses in few easy steps:

  1. Click here to make a copy of the Google Sheet for performing IP lookups in bulk.

  2. Paste the list of IP addresses in column A, one per row. The lookup service works for both IPv4 and IPv6 addresses.

  3. Enter your key in cell E1. If you have a small list of IP address, use demo as the key or get your own API key from

  4. Click the Run button, authorize the script and watch as the geographic details and ISP names are populated in the sheet.

IP2Location Web Service Demo

How IP2Location Script Works

Internally, the Google Sheet uses the IP2location web service with Google Apps Script to transform IP addresses into geographic region.

It uses the UrlFetchApp service to perform multiple HTTP requests in a single batch for improved performance. Here’s the full source code:

const ip2location = () => {
  // Get all the input data from Google Sheet
  const ss = SpreadsheetApp.getActiveSheet();
  const data = ss.getDataRange().getDisplayValues();

  // Use your own API key or use demo key
  const apiKey = data[0][4] || "demo";

  // Generate API URL for IP address
  const getUri_ = (ipAddress) => {
    const API_URL = "";
    return `${API_URL}/?ip=${ipAddress}&key=${apiKey}&package=ws4`;

  const requests = [];

  for (let r = 2; r < data.length; r++) {
    const [ipAddress, countryName] = data[r];
    // Only process rows where the country is blank
    if (ipAddress && !countryName) {
      requests.push({ url: getUri_(ipAddress), rowNumber: r + 1 });

  // Make API calls in bulk using the UrlFetchApp service
  UrlFetchApp.fetchAll(requests).forEach((content, i) => {
    // Parse the JSON response
    const { city_name, country_name, isp, response } = JSON.parse(content);

    // If the response is populated, the API call failed
    if (response) throw new Error(response);

    // Write the response data to Google Sheet
    const values = [[country_name, region_name, city_name, isp]];
    ss.getRange(requests[i].rowNumber, 2, 1, 4).setValues(values);

  // Flush all changes

How Spammers Avoid the Gmail Spam Filter through Google Forms

Gmail is very effective at filtering spam emails but spammers seem to have figured out a new way to bypass the spam filters and send emails that land right in the user’s inbox. The emails are sent through Google Forms and because the messages originate from Google’s own email servers, they do not get caught in the spam filters.

Google Forms - Spam Emails

Here’s how spam emails are sent through Google Forms.

  1. A public form is created with Google Forms.
  2. The form creator uploads images for the various question fields and also adds links to spam websites in the form.
  3. Inside the Form settings, they turn on the option to “Collect Email Addresses” including the option to send “Response receipts” when a new form is submitted.

Google Form Email

Now the spammers can simply open the Google Form, fill in the recipient’s email address and hit the submit button.

Google Forms will automatically email a copy of the form response, including all the pictures and links contained in the original form, to the email address that was entered in the form.

Here’s a screenshot of one such email from Google Forms that easily tricked the spam filters.

Google Forms

How to Block Spam from Google Forms

If you would like to prevent spam emails from Google Forms from landing in your inbox, Gmail filters can help.

All pre-filled Google Forms emails have the sender’s email address as below:

You can create a filter in Gmail that will automatically delete emails that have Google Forms as the sender.

Google Forms Filter

Alternatively, you may open the form link from the email and click the “Report Abuse” button to report the form to Google. That is not likely to be a very effective strategy though as spammers can always switch to a different Google account.

Learning Vim for Beginners

Vim, or Vi Improved, is a powerful text editor that lets you do almost everything using keyboard shortcuts. You can replace text in a document, move or delete lines, automate edit actions, and more, without ever reaching for the mouse. Vim is the favorite source code editor of programmers but there’s no reason why you cannot use this editor for writing documents or composing long emails.

Vim can be confusing for people who are used to working inside visual editors like Microsoft Word or Google Docs but spend some time with Vim and it will be difficult for you to go back. Entire books have been devoted to teaching Vim but if you can manage to learn the basic commands, you’ll find yourself more efficient and productive.

Vim Logo

How to Learn Vi

Here’s a list of online tutorials and other helpful resources to help you learn Vim.

1. OpenVim - An interactive tutorial for learning the basics of Vim. Switch to the Practice page to test your existing Vim skills.

2. Vim Adventures - An online puzzle game for learning and memorizing Vim commands. You play the character of a blinking cursor that has to navigate the maze with the letter keys. If you are stuck, you can always type :help for a hint.

3. Vim Genius - This a flashcard style game to help you learn the basics of Vim. There are dedicated lessons for learning the motion keys (h,j,k,l) and for mastering copy-paste in vim.

4. Learn to Love Vim - The Linux Voice magazine has put together a quick video tutorial to get you started with Vim.

5. Vim Basics - Derek Wyatt has produced a bunch of video tutorials (screencasts) around teaching Vim. A good resource for novice users who prefer learning Vim by watching than reading.

6. Learning Vim - Mike Coutermarsh covers getting up and running, and eventually productive with Vim.

7. Vim - Precision Editing - Drew Neil, author of the popular Practical Vim title and, walks you through Vim and how the text editor is optimized for mouseless operations.

8. Vim Tutorial - The official Vim documentation is excellent and includes a step-by-step tutorial. You can also access this tutorial inside the Vim program through the :vimtutor command.

9. Vim Cheat Sheet - Print this because you’ll need it later.

10. Vim Masterclass - This Udemy course will help you master all the concepts of Vim and how to ‘think’ in Vim.

If you spend a lot of time typing text, learning Vim will be totally worth the effort. I wrote this article inside Visual Studio Code with Vim key bindings.

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();

const onFormSubmit = ({ response } = {}) => {
  try {
    // Get a list of all files uploaded with the response
    const files = response
      // We are only interested in File Upload type of questions
        (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
  } catch (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);

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);


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) {
  function printInterests() {
    console.log("Calling private method");
  return {
    printInterests: printInterests,
    addInterest: addInterest,


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() {
    return {
      printName: printName,
  if (!win.personModule) {
    win.personModule = personModule;
  } else {
    throw new Error("Cannot initialize application");


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 => {
    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