Find Free Udemy Courses with Google Sheets and the Udemy API

Whether you are looking to learn a programming language, enhance your Microsoft Excel skills, or acquire knowledge in Machine Learning, Udemy probably has a video course for you. Udemy courses are usually affordable, there are no subscription fee and you can learn at your own pace.

Free Udemy Courses on Programming

While most video tutorials on Udemy require payment, the website also offers some of their highly-rated courses for free. I’ve prepared a Google Sheet that lists all the free programming courses currently available on Udemy. The spreadsheet is updated automatically every few hours. You can also access the web version for easy browsing.

Free Udemy Courses ✨ You may use the search function of the browser (Ctrl + F) to find courses for a specific programming language or topic. The courses are sorted by popularity.

There’s no secret sauce. Udemy has an developer API that provides access to all the course data available on the website, including user ratings, number of students who have taken the course, duration, preview video lectures, and more.

Use the Udemy API with Google Sheets

The Udemy API is free to use but requires authentication. You can generate the credentials for your Udemy account and then use the /courses endpoint to fetch the list of free courses.

const parseCourseData_ = (courses) =>
  courses
    .filter(
      ({ is_paid, primary_category }) =>
        is_paid === false && ['Development', 'IT & Software'].includes(primary_category.title)
      // We are primarily interested in programming courses on Udemy
    )
    .map((e) => [
      `=IMAGE("${e.image_240x135}")`,
      `=HYPERLINK("https://www.udemy.com${e.url}";"${e.title}")`,
      e.visible_instructors.map(({ display_name }) => display_name).join(', '),
      e.num_subscribers,
      Math.round(e.avg_rating * 100) / 100,
      e.num_reviews,
      e.content_info_short,
      e.num_lectures,
      new Date(e.last_update_date),
    ]);

const listUdemyCoursesGoneFree = () => {
  // Put your Udemy credentials here
  const CLIENT_ID = '';
  const CLIENT_SECRET = '';

  const params = {
    page: 1,
    page_size: 100,
    is_paid: false,
    'fields[course]': '@all',
  };

  const query = Object.entries(params)
    .map(([key, value]) => `${key}=${encodeURIComponent(value)}`)
    .join('&');

  const apiUrl = `https://www.udemy.com/api-2.0/courses/?${query}`;
  const bearer = Utilities.base64Encode(`${CLIENT_ID}:${CLIENT_SECRET}`);
  const options = {
    muteHttpExceptions: true,
    headers: {
      Authorization: `Basic ${bearer}`,
    },
  };

  const courses = [];

  do {
    const response = UrlFetchApp.fetch(apiUrl, options);
    const { results = [], next } = JSON.parse(response);
    courses.push(...parseCourseData_(results));
    url = next;
  } while (url && courses.length < 500);

  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const [sheet] = ss.getSheets();
  sheet.getRange(2, 1, sheet.getLastRow(), sheet.getLastColumn()).clearContent();
  sheet.getRange(2, 1, courses.length, courses[0].length).setValues(courses);
};

We use the UrlFetch service of Google Scripts to fetch the data from the Udemy API and the data is then parsed and inserted into the Google Sheet. The course thumbnail image is rendered using the IMAGE formula and the course title is linked to the Udemy website using the HYPERLINK formula.

How to Import MailChimp Subscribers to Google Sheets

The Gmail Mail Merge addon can now import the email addresses of subscribers from your MailChimp mailing lists into Google Sheets. If you wish to send emails to your subscribers directly from Gmail, instead of using MailChimp mail servers, this is the way to go.

As a developer, you can use Google Apps Script to import subscriber lists, HTML campaigns, performance reports and any other data from MailChimp to Google Sheets for analysis. You can use the MailChimp OAuth2 library but in this example, we’ll use the developer key directly to connect to MailChimp.

Get the MailChimp Developer Key

In your Mailchimp account, navigate to the Account page. In the drop-down menu, select Extras, and then API keys. Click Create A Key and make a note of it.

Google Apps Script - Get MailChimp Audiences

const MAILCHIMP_API_KEY = '<<API_KEY_HERE>>';

// MailChimp API key includes the data center id
// that your MailChimp account is associated with
const makeHttpRequest = (endpoint, params = {}) => {
  const [, mailchimpDataCenter] = MAILCHIMP_API_KEY.split('-');
  const url = `https://${mailchimpDataCenter}.api.mailchimp.com/3.0/${endpoint}`;
  const qs = Object.keys(params)
    .map(key => `${key}=${params[key]}`)
    .join('&');
  const apiUrl = qs ? `${url}?${qs}` : url;
  const request = UrlFetchApp.fetch(apiUrl, {
    method: 'GET',
    headers: {
      Authorization: `Basic ${Utilities.base64Encode(`labnol:${MAILCHIMP_API_KEY}`)}`
    }
  });
  return JSON.parse(request);
};

const getListMembers = (id, offset) => {
  const { members } = makeHttpRequest(`lists/${id}/members`, {
    count: 100,
    offset,
    fields: 'members.email_address',
    status: 'subscribed',
    sort_field: 'last_changed',
    sort_dir: 'DESC'
  });
  return members.map(({ email_address: email }) => [email]);
};

// Get a list of all subscribers of a specific
// MailChimp mailing list, you can retrieve the email address,
// name and subscription statues of subscribers
const getMailChimpListMembers = id => {
  let hasMore = true;
  let data = [];
  do {
    const emails = getListMembers(id, data.length);
    data = [...data, ...emails];
    hasMore = emails.length > 0;
  } while (hasMore);
  return data;
};

// Get a list of all audiences / lists from MailChimp
const getMailChimpLists = () => {
  const params = { count: 10, fields: 'lists.id,lists.name', sort_field: 'date_created', sort_dir: 'DESC' };
  const { lists = [] } = makeHttpRequest('lists', params);
  return lists.map(({ id, name }) => ({ id, name, members: getMailChimpListMembers(id) }));
};

The GetMailChimpLists method will bring all the lists and associated email addresses in a JSON object that you can easily write to Google Sheets using the SpreadsheetApp service.

How to Move your iCloud and Apple Photos to Google Photos

A friend writes - “Any suggestions on how to combine the Google photo library with iPhoto. Which is a better platform for keeping the photos? Google seems to be very handy in sorting and searching. Would love to know your views”

I am a big fan of Google Photos for several reasons - you get unlimited storage space, Google is pretty good at visual image search and you can have collaborative photo albums where multiple people can upload to a common folder.

Transfer Photos from Apple iCloud / Mac to Google Photos

If you would like to copy your photos from iCloud / Apple Photos to Google Photos, there are no browser plugins or software that can automate this - you’ll have to manually transfer the picture library from Apple to Google Photos. Luckily, that migration process isn’t difficult either.

It is a two-step process - you download the photos from iPhoto and iPad to your computer via iCloud and then put them on to the Google Cloud. Let’s see how:

Step 1: Download Photos from iCloud

Via Web Browser

You may directly go to the icloud.com/photos website, select your photos and then click the download button to save them from the iCloud library to your Windows PC or Mac.

Download Photos from the iCloud website

On Windows PC

If you have photos on your iPhone or iPad that are getting backed up on iCloud, you can copy them to your Windows PC with iCloud for Windows.

Inside iCloud, sign-in with your Apple ID, then open the File Explorer window, click on iCloud Photos under Quick Access and then choose Download photos and videos.

On Apple Mac OS

Open the Apple Photos app on your Mac and press ^1 (Ctrl+1) to switch to the main Photo view that has a list of all pictures that are available in your iPhoto library.

Select one or more photos, then go to the File menu and choose Export to download pictures from Apple Photos to another folder on your desktop.

Include Location in Photos

For the export options, you may stick to the default values but do check the “Include Location Information” option. This will help Google group your photos by location.

Also, if you aren’t seeing all your iPhone photos inside Mac, go to Preferences inside the Photos app and make sure that the Download originals to this Mac option is checked under the iCloud Photos section.

Download Original Photos from iCloud

Step 2 - Upload Photos to Google Photos

Once you have saved the photos that you wish to transfer to your local drive, you need to send them to Google Photos and there are two ways to go about it.

Upload Photos via Web Browser

Open Google Chrome, or any other web browser, and go to photos.google.com. Simply drag the photos folder from your desktop to the Google Photos website and they’ll be uploaded in sequence.

The browser should remain open and your Internet connection should be working for the upload to happen in the background.

Upload Photos via Google App

If you have a large number of photos to upload from your Windows PC or Mac to the Google Photos library, it is recommended that you use Google’s Backup and Sync tool that is available for both Windows and Mac OS.

Upload Apple Photos to Google Photos

With the app installed, sign-in with your Google account, select the folders on your desktop that you wish to backup and click Start to initiate the backup process.

While the name is Backup and Sync, it is not exactly a synchronization tool. So once your photos are uploaded to Google Photos, you can remove them from the local drive and they won’t be deleted from your Google Photos.

The Best Online Tools To Know Everything About a Website

How do I contact the owner of a website? Where is a particular website hosted? What other websites are hosted on that same server? Is the site using WordPress or Gatsby? Which ad networks are they using to monetize a site? Is my site accessible from China?

Here are some of the most useful online tools that will help you know every single detail of any website.

Also see: The Essentials Tools for Programmers

  • just-ping.com — Use Just Ping to determine if a particular website is accessible from other countries. Just Ping has monitoring servers across the world including Turkey, Egypt, and China so if the ping results say 100% Packet Loss, most likely the site is inaccessible from that region.
  • who.is — If you like to know the contact address, email and phone number of the website owner, this free whois lookup service will help. This is a universal lookup service meaning it can simultaneously query the whois database of all popular domain registrars.
  • whoishostingthis.com — Enter the URL of any website and this online service will show you the name of the company where that website is hosted. This may come handy if you need the contact information of the web hosting provider for writing a DMCA Notice or if you are looking to switch web hosts.
  • chillingeffects.org — When there’s a copyright-related complaint against a website, a copy of that letter is archived in the Chilling Effects database. Anyone can query this public database to know about all the copyright infringement complaints against a particular website.
  • myip.ms — MyIP.ms offers a comprehensive report of any website or I.P. Address. You get to know about the hosting provider, the physical location of a website, the IP Address change history of a website and the DNS information. Netcraft also offers similar reports.
  • reversewhois.com — The reverse whois lookup will help you determine other websites of someone. You can search the whois database by the email address or name of the domain registrant.
  • builtwith.com — Use BuiltWith to know the technology stack of any website. It helps you figure out the mail service provider of a domain, the advertising partners, the tracking widgets that are installed on a website and whether the site is using any CDN like Amazon S3 or Google Cloud. See example.
  • ssllabs.com - The certificate diagnostics tool will verify your site’s SSL certificate and ensure that it is correctly installed, trusted and does not show errors to any of your site visitors.
  • semrush.com — If you wish to analyze your competitor’s website, this is the tool to go with. SEM Rush will help you figure what organic keywords are people using to find a website, what is the site’s traffic and which are the competing websites.
  • dnsmap.io — When you buy a new domain or switch from one host to another, the DNS records for the domain changes and it may take a while to propagate these changes worldwide. The tool checks the DNS records from various geographic locations and it can check your domain’s A, CNAME, TXT and MX records. whatsmydns.net is also a good alternative.
  • toolbox.googleapps.com — If email messages, including those sent via Mail Merge, from your domain are not reaching the recipient’s mailbox, use this Google tool to confirm that DMARC, DKIM and SPF records are properly configured for your domain.
  • browserstack.com - Check your website’s responsive design on multiple desktops, tables, iOS and Android phones running different versions of operating systems.
  • screenshot.guru - If a website is inaccessible, use Screenshot Guru, hosted on the Google Cloud, to confirm if the website is down or not.
  • thinkwithgoogle.com - A mobile speed tool developed by Google that will help you determine how fast your websites will load on mobile phones on 3G and 4G network. You can also compare your mobile speed score with other websites.
  • testmysite.io - A simple site testing tool from Netlify that will measure and rank your site’s loading time from different regions around the world.
  • developers.google.com — Find the Page Speed score of any website on both desktop and mobile devices. The higher this number, the better. The Google tool also offers suggestions on how the score can be improved.
  • httparchive.org — The HTTP Archive is a repository of all performance-related metrics for a website. It keeps a record of the size of pages, their average load time and the number of failed requests (missing resources) over time.
  • Website Monitor - Use this open-source Google Sheets based website monitoring tool to get alerts when your domain goes down or is inaccessible.
  • Flush DNS - Use this tool to flush the Google DNS cache for a domain. If you changed the DNS servers for your domain, by changing registrars or DNS hosting in the last few days, flush your main domain name first before you flush any subdomains. OpenDNS also has a web tool for refreshing the DNS cache.
  • DomainTools - The tool monitors one or more web domains and sends email alerts when the domain is expiring, the domain gets renewed, the nameservers change or when the registrant information is updated for the domain.

Also see: 101 Most Useful Websites

Block All Incoming and Outgoing Emails Except Specific Whitelisted Domains

The finance team in an organization would like to use Gmail for internal communication only. The corporate email policy restricts the finance team from sharing any files or email messages with external teams but the employees are allowed to exchange emails within the team.

Google makes it easy to implement such an email policy in Gmail for GSuite customers.

Block Incoming Emails in Gmail

To get started, sign-in to admin.google.com as your GSuite domain admin and go to Apps > GSuite Core Services > Gmail > Advanced Settings.

Inside the General Settings tab, navigate to Restrict Delivery and click the Configure button to restrict the domains that your employees are allowed to exchange emails with.

Under the Add addresses section, specify one or more domains and email addresses that employees are allowed to send and receive email messages from.

Whitelist domains and email addresses in Gmail

You can specify inputs in the following format:

  1. harvard.edu - Allow emails from everyone in the domain
  2. *.harvard.edu - Allow emails from all subdomains
  3. finance.harvard.edu - Allow emails from a specific subdomain
  4. admin@harvard.edu - Allow emails from an email address

When adding domains in the whitelist, it is recommended that you turn on sender authentication to disallow spoofed emails (where the actual sender is different from the FROM address mentioned in the email header). Gmail uses the SPF and DKIM records to verify if the sender is authenticated.

Save the settings and employees would be limited to sending emails to specific domains only.

How to Get the Quiz Score in Google Forms with Apps Script

Teachers can use Google Forms to create an online quiz and students can view their test scores immediately after form submission. With Apps Script, you can set up automatic email notifications and send quiz scores to parents after a student has taken the quiz.

Here’s a sample Google Script that will iterate through every answer in the most recent Google Form response and log the max score (points) of a gradable question and the score for the respondent’s submitted answer.

function getGoogleFormQuizScore() {

  // Returns the form to which the script is container-bound.
  var form = FormApp.getActiveForm();

  // Get the most recently submitted form response
  var response = form.getResponses().reverse()[0];

  // Gets an array of all items in the form.
  var items = form.getItems();

  for (var i=0; i<items.length; i++) {

    var question = items[i];

    // Get the item's title text
    var qTitle = question.getTitle();

    // Get the item's type like Checkbox, Multiple Choice, Grid, etc.
    var qType = question.getType();

    // Gets the item response contained in this form response for a given item.
    var responseForItem = response.getResponseForItem(question)

    //Gets the answer that the respondent submitted.
    var answer = responseForItem ? responseForItem.getResponse() : null;

    var item = castQuizItem_(question, qType);

    // Quiz Score and Maximum Points are not available
    // for Checkbox Grid and Multiple Choice Grid questions
    // through they are gradable in the Google Form

    if (item && typeof item.getPoints === "function") {

      var maxScore = item.getPoints();
      var gradableResponseForItem = response.getGradableResponseForItem(question);
      var score = gradableResponseForItem.getScore();

      Logger.log(String(qType), qTitle, answer, maxScore, score);

    }
  }
}

The Google Forms API can only return scores for Multiple Choice, Dropdown and Checkbox style questions. It cannot provide scores for the grid type of questions where the item is presented as a grid of rows and columns.

  1. Checkbox Grid - A question item that allows the respondent to select multiple choices per row from a sequence of checkboxes.
  2. Choice Grid - A question item that allows the respondent to select one choice per row from a sequence of radio buttons.
function castQuizItem_(item, itemType) {
  if (itemType === FormApp.ItemType.CHECKBOX) {
    return item.asCheckboxItem();
  }
  if (itemType === FormApp.ItemType.DATE) {
    return item.asDateItem();
  }
  if (itemType === FormApp.ItemType.DATETIME) {
    return item.asDateTimeItem();
  }
  if (itemType === FormApp.ItemType.DURATION) {
    return item.asDurationItem();
  }
  if (itemType === FormApp.ItemType.LIST) {
    return item.asListItem();
  }
  if (itemType === FormApp.ItemType.MULTIPLE_CHOICE) {
    return item.asMultipleChoiceItem();
  }
  if (itemType === FormApp.ItemType.PARAGRAPH_TEXT) {
    return item.asParagraphTextItem();
  }
  if (itemType === FormApp.ItemType.SCALE) {
    return item.asScaleItem();
  }
  if (itemType === FormApp.ItemType.TEXT) {
    return item.asTextItem();
  }
  if (itemType === FormApp.ItemType.TIME) {
    return item.asTimeItem();
  }
  if (itemType === FormApp.ItemType.GRID) {
    return item.asGridItem();
  }
  if (itemType === FormApp.ItemType.CHECKBOX_GRID) {
    return item.asCheckboxGridItem();
  }
  if (itemType === FormApp.ItemType.PAGE_BREAK) {
    return item.asPageBreakItem();
  }
  if (itemType === FormApp.ItemType.SECTION_HEADER) {
    return item.asSectionHeaderItem();
  }
  if (itemType === FormApp.ItemType.VIDEO) {
    return item.asVideoItem();
  }
  if (itemType === FormApp.ItemType.IMAGE) {
    return item.asImageItem();
  }
  return null;
}

Quiz in Google Forms with Score

Google Form Quiz