appscript.dev
Automation Intermediate Sheets Gmail

Monitor Reddit or Hacker News for keywords

Watch for Northwind brand and topic mentions across public forums and log to a sheet.

Published Sep 21, 2025

When someone posts about Northwind on Hacker News, the team wants to know quickly — to answer a question, thank a fan, or get ahead of a complaint. But nobody is going to refresh a search page all day, and by the time a mention is spotted by chance the thread has often moved on.

This script does the watching. It searches Hacker News for each keyword you care about, logs any story it has not seen before to a Sheet, and emails the team the moment a new mention appears. The Sheet doubles as a record of every mention over time, and the de-duplication means you are only alerted once per thread.

What you’ll need

  • A Google Sheet to log mentions into, with its ID copied into the config below. The script writes to the first tab and expects mention URLs to live in column D.
  • A Gmail account that can send to your team — the script sends from whoever owns the Apps Script project.
  • Nothing else. The Hacker News search API (Algolia) is free and needs no API key.

The script

// Keywords to watch for across Hacker News.
const KEYWORDS = ['northwind studios', 'appscript.dev'];

// The Sheet that logs every mention.
const MENTIONS_SHEET_ID = '1abcMentionsId';

// Where new-mention alerts are sent.
const ALERT_EMAIL = '[email protected]';

// How many of the newest stories to check per keyword.
const RESULTS_PER_KEYWORD = 5;

/**
 * Searches Hacker News for each keyword and processes the newest
 * matching stories. Designed to run on a recurring trigger.
 */
function scanHn() {
  for (const keyword of KEYWORDS) {
    // 1. Search HN's Algolia index for stories matching this keyword.
    const url =
      'https://hn.algolia.com/api/v1/search' +
      '?query=' + encodeURIComponent(keyword) +
      '&tags=story';
    const res = JSON.parse(UrlFetchApp.fetch(url).getContentText());

    // 2. Walk the newest few hits and hand each to logIfNew.
    for (const hit of (res.hits || []).slice(0, RESULTS_PER_KEYWORD)) {
      const itemUrl = 'https://news.ycombinator.com/item?id=' + hit.objectID;
      logIfNew(keyword, hit.title, itemUrl);
    }
  }
}

/**
 * Logs a mention to the Sheet and emails the team — but only if the
 * story's URL has not been seen on a previous run.
 */
function logIfNew(keyword, title, url) {
  const sheet = SpreadsheetApp.openById(MENTIONS_SHEET_ID).getSheets()[0];

  // 1. Build a set of every URL already logged (column D) and skip
  //    anything we have seen before — this is the de-duplication.
  const known = new Set(sheet.getRange('D2:D').getValues().flat().filter(Boolean));
  if (known.has(url)) return;

  // 2. New mention — append a dated row to the log.
  sheet.appendRow([new Date(), keyword, title, url]);

  // 3. Email the team so they can react while the thread is live.
  GmailApp.sendEmail(
    ALERT_EMAIL,
    'New mention: ' + keyword,
    title + '\n\n' + url
  );
  Logger.log('New mention logged: ' + title);
}

How it works

  1. scanHn loops over every keyword in KEYWORDS. For each, it queries the Hacker News Algolia search API with tags=story, so comments are ignored and only top-level stories come back.
  2. It takes the newest RESULTS_PER_KEYWORD hits, builds the canonical HN item URL from each story’s objectID, and passes the keyword, title, and URL to logIfNew.
  3. logIfNew reads column D of the log Sheet — the URL column — into a Set. That set is the memory of every mention already recorded. If the incoming URL is in it, the function returns and nothing happens.
  4. For a genuinely new mention it appends a dated row to the Sheet, then emails the team the title and link so they can respond while the thread is active.

Example run

Hacker News search returns hits like this:

{
  "hits": [
    { "objectID": "41250001", "title": "Northwind Studios open-sources its build tools" }
  ]
}

The URL https://news.ycombinator.com/item?id=41250001 is not yet in column D, so the script logs a row:

DateKeywordTitleURL
2025-09-21 09:00northwind studiosNorthwind Studios open-sources its build toolshttps://news.ycombinator.com/item?id=41250001

…and sends the team an email:

FieldValue
SubjectNew mention: northwind studios
BodyNorthwind Studios open-sources its build tools — https://news.ycombinator.com/item?id=41250001

On the next run the same story is found again, but its URL is now in the set, so logIfNew skips it — no duplicate row, no second email.

Trigger it

To keep watch without anyone refreshing a search page, run it on a schedule:

  1. In the Apps Script editor, open Triggers (the clock icon).
  2. Click Add Trigger.
  3. Choose scanHn, event source Time-driven, type Hour timer, and pick Every 6 hours for a balance of freshness and quota.
  4. Save and approve the authorisation prompt.

The script then checks for new mentions through the day and only ever emails you about stories it has not seen before.

Watch out for

  • De-duplication keys on the exact URL in column D. If you ever edit those cells, or clear the Sheet, previously seen stories will be treated as new and re-alerted.
  • This searches Hacker News only, despite the title. Reddit’s API now requires authentication, so add it as a separate, keyed integration rather than dropping its URL into this script.
  • Algolia’s search endpoint sorts by relevance, not date. search_by_date returns the genuinely newest stories — switch to it if you care more about catching mentions early than about ranking.
  • Broad keywords cause noise. A common word will match unrelated stories and flood the team’s inbox; keep KEYWORDS specific to your brand and products.
  • Consumer Gmail caps daily sends. A handful of alerts a day is fine, but a sudden burst of mentions could hit the limit — batch them into one digest email if that becomes a real risk.
  • The HN search API is free but unmetered politeness still applies. Every 6 hours is comfortable; do not run it every minute.

Related