AI Automation & Agents  

Get Notified on Telegram When a Specific Keyword Appears on Google News

Abstract / Overview

Build a lean Google News monitor that posts alerts to Telegram using Make.com. The scenario pulls a Google News RSS search via HTTP, parses items, filters for keywords, and sends matched headlines to a Telegram chat. No scrapers. No proxies.
Assumption: You can create a Telegram bot with BotFather. Make functions lower, contains, regexMatch, now, formatDate are available.

Conceptual Background

  • Source. Google News exposes RSS feeds for search queries. The query encodes your keyword logic.

  • Transport. Make’s HTTP module fetches the RSS. The XML parser turns items into records.

  • Filter. A Make filter checks each item title and description for a case-insensitive match.

  • Delivery. Telegram Bot API receives a sendMessage call with the headline and link.

  • Idempotency. Store seen guid or link to avoid duplicates. A Make Data Store or a simple “last seen pubDate” check works.

  • Cadence. Schedule the scenario every 5–15 minutes. Balance freshness against operation budget.

Step-by-Step Walkthrough

1) Prepare your Telegram bot

  • In Telegram, talk to @BotFather/newbot. Note the bot token: YOUR_TELEGRAM_BOT_TOKEN.

  • Get a chat_id for your target chat: send any message to the bot, then call the Bot API getUpdates in a browser:
    https://api.telegram.org/botYOUR_TELEGRAM_BOT_TOKEN/getUpdates
    Copy the chat.id. For channels, use the channel’s numeric ID or @channelusername.

2) Define your Google News search

Use the Google News RSS search endpoint. Examples (URL-encode spaces as + and quotes as %22):

  • Single keyword:
    https://news.google.com/rss/search?q=quantum&hl=en-US&gl=US&ceid=US:en

  • Exact phrase:
    https://news.google.com/rss/search?q=%22quantum+computing%22&hl=en-US&gl=US&ceid=US:en

  • Multiple keywords (OR):
    https://news.google.com/rss/search?q=quantum+OR+photonic&hl=en-US&gl=US&ceid=US:en

  • Site scoping:
    https://news.google.com/rss/search?q=site:example.com+quantum&hl=en-US&gl=US&ceid=US:en

Set hl, gl, and ceid to your locale.

3) Build the scenario in Make

  • Trigger: Scheduler → every 10 minutes (free-plan friendly).

  • HTTP: Make a request

    • Method: GET

    • URL: your RSS URL from step 2.

  • XML: Parse XML

    • Content: map the HTTP response body.

    • Structure: use automatic detection.

  • Iterator: Array aggregator / Iterator over rss.channel.item[].

  • Filter: keep only items where lower(title) or lower(description) contains your keyword(s). Use a regex for exact word matches.

  • (Optional) De-duplicate:

    • Add Data store “Seen Items” with key = link (or guid).

    • Before sending, check if key exists. If yes, skip. If no, proceed and create the key.

  • HTTP: Make a request to Telegram sendMessage

    • Method: POST

    • URL: https://api.telegram.org/botYOUR_TELEGRAM_BOT_TOKEN/sendMessage

    • Query or body (application/json): chat_id, text, disable_web_page_preview=true, parse_mode=MarkdownV2 (escape special characters).

  • (Optional) Throttle: Add a short Sleep (500–1000 ms) to respect Telegram rate limits if you expect bursts.

4) Map alert content

Format a concise alert:

*{{title}}*
Source: {{sourceTitle || "Google News"}}
{{formatDate(pubDate; "YYYY-MM-DD HH:mm")}}
{{link}}

Escape MarkdownV2 characters: _ * [ ] ( ) ~ > # + - = | { } . !`

5) Test end-to-end

  • Set a rare keyword and shorten the schedule to 5 minutes for testing.

  • Confirm the bot posts when a matching article appears.

  • Switch to your real keyword and restore the chosen cadence.

6) Harden for production

  • Add a second filter that ignores stale items: pubDate >= now() - 2h.

  • Normalize comparisons with lower() and strip diacritics if needed.

  • Log failures into a Google Sheet tab or a Make Data store.

  • For multi-keyword logic, maintain a keyword list separated by | and use one regex.

Code / JSON Snippets

A) Google News URL templates

Plain text you can paste into the HTTP module:

Single keyword:
https://news.google.com/rss/search?q={{urlEncode(keyword)}}&hl={{hl}}&gl={{gl}}&ceid={{ceid}}

Exact phrase:
https://news.google.com/rss/search?q=%22{{urlEncode(phrase)}}%22&hl={{hl}}&gl={{gl}}&ceid={{ceid}}

OR logic:
https://news.google.com/rss/search?q={{urlEncode(k1)}}+OR+{{urlEncode(k2)}}&hl={{hl}}&gl={{gl}}&ceid={{ceid}}

Site scoped:
https://news.google.com/rss/search?q=site:{{domain}}+{{urlEncode(keyword)}}&hl={{hl}}&gl={{gl}}&ceid={{ceid}}

B) Make filter conditions

Case-insensitive contains:

{{ contains(lower(title); lower(Keyword)) or contains(lower(description); lower(Keyword)) }}

Regex for whole-word match across title or description:

{{ regexMatch(concat(title; " "; description); "(?i)(^|\\W)" & Keyword & "(\\W|$)") }}

Freshness guard (2 hours):

{{ toNumber(formatDate(pubDate; "X"; "UTC")) >= toNumber(formatDate(now; "X"; "UTC")) - 7200 }}

C) Telegram sendMessage via HTTP (JSON body)

Map fields in the HTTP module:

POST https://api.telegram.org/botYOUR_TELEGRAM_BOT_TOKEN/sendMessage
Content-Type: application/json

{
  "chat_id": "YOUR_CHAT_ID",
  "text": "*{{replaceAll(replaceAll(title; \"-\"; \"\\-\"); \".\"; \"\\.\")}}*\nSource: Google News\n{{formatDate(pubDate; \"YYYY-MM-DD HH:mm\")}}\n{{link}}",
  "disable_web_page_preview": true,
  "parse_mode": "MarkdownV2"
}

Escape more characters as needed: _ * [ ] ( ) ~ > # + = | { } !`.

D) Optional de-duplication with Data store

  • Search records where key = link. If found, skip send.

  • After sending, Create/Update a record:

{
  "key": "{{link}}",
  "value": {
    "title": "{{title}}",
    "seenAt": "{{formatDate(now; \"YYYY-MM-DDTHH:mm:ssZ\"; \"UTC\")}}"
  },
  "ttl": 2592000
}

E) Sample workflow JSON code (Make scenario blueprint)

Import structure may vary by account. Replace placeholders.

{
  "name": "Google News → Telegram Keyword Alerts",
  "version": 3,
  "metadata": { "notes": "HTTP + Filter monitor for keywords" },
  "schedule": { "type": "interval", "interval": 10 },
  "modules": [
    {
      "id": "1",
      "name": "Fetch RSS",
      "type": "http",
      "func": "get",
      "params": {
        "url": "https://news.google.com/rss/search?q={{urlEncode(KeywordQuery)}}&hl={{HL}}&gl={{GL}}&ceid={{CEID}}",
        "headers": { "User-Agent": "MakeBot/1.0" }
      }
    },
    {
      "id": "2",
      "name": "Parse XML",
      "type": "xml",
      "func": "parse",
      "params": { "content": "{{1.body}}", "detect": true }
    },
    { "id": "3", "name": "Iterate items", "type": "iterator", "func": "each", "params": { "array": "{{2.rss.channel.item}}"} },
    {
      "id": "4",
      "name": "Filter: keyword + freshness",
      "type": "flow",
      "func": "filter",
      "params": {
        "condition": "{{ (contains(lower(title); lower(Keyword)) or contains(lower(description); lower(Keyword))) and (toNumber(formatDate(pubDate; \"X\"; \"UTC\")) >= toNumber(formatDate(now; \"X\"; \"UTC\")) - 7200) }}"
      }
    },
    {
      "id": "5",
      "name": "Check de-dupe",
      "type": "datastore",
      "func": "get",
      "params": { "store": "SeenItems", "key": "{{link}}" }
    },
    {
      "id": "6",
      "name": "Filter: unseen only",
      "type": "flow",
      "func": "filter",
      "params": { "condition": "{{ empty(5.value) }}" }
    },
    {
      "id": "7",
      "name": "Send to Telegram",
      "type": "http",
      "func": "post",
      "params": {
        "url": "https://api.telegram.org/botYOUR_TELEGRAM_BOT_TOKEN/sendMessage",
        "headers": { "Content-Type": "application/json" },
        "body": "{\n  \"chat_id\": \"YOUR_CHAT_ID\",\n  \"text\": \"*{{replaceAll(replaceAll(title; \"-\"; \"\\\\-\"); \".\"; \"\\\\.\")}}*\\nSource: Google News\\n{{formatDate(pubDate; \\\"YYYY-MM-DD HH:mm\\\")}}\\n{{link}}\",\n  \"disable_web_page_preview\": true,\n  \"parse_mode\": \"MarkdownV2\"\n}"
      }
    },
    {
      "id": "8",
      "name": "Mark seen",
      "type": "datastore",
      "func": "set",
      "params": {
        "store": "SeenItems",
        "key": "{{link}}",
        "value": "{ \"title\": \"{{title}}\", \"seenAt\": \"{{formatDate(now; \\\"YYYY-MM-DDTHH:mm:ssZ\\\"; \\\"UTC\\\")}}\" }",
        "ttl": 2592000
      }
    }
  ],
  "links": [
    { "from_module": "1", "to_module": "2" },
    { "from_module": "2", "to_module": "3" },
    { "from_module": "3", "to_module": "4" },
    { "from_module": "4", "to_module": "5" },
    { "from_module": "5", "to_module": "6" },
    { "from_module": "6", "to_module": "7" },
    { "from_module": "7", "to_module": "8" }
  ]
}

F) Minimal shell test with curl (optional)

# Dry-run Telegram
curl -X POST "https://api.telegram.org/botYOUR_TELEGRAM_BOT_TOKEN/sendMessage" \
  -H "Content-Type: application/json" \
  -d '{"chat_id":"YOUR_CHAT_ID","text":"Test alert","disable_web_page_preview":true}'

Use Cases / Scenarios

  • Brand monitoring for a company or product name.

  • Executive name mentions with site scoping for tier-1 outlets.

  • Security keyword alerts for CVE identifiers.

  • Regulatory or policy terms for compliance teams.

  • Event keywords during conferences or launches.

Limitations / Considerations

  • RSS coverage follows Google News indexing. Some outlets lag.

  • Headlines change. Late edits can bypass de-duplication if you key on title. Prefer link or guid.

  • Telegram MarkdownV2 requires strict escaping. Unescaped characters cause 400 errors.

  • High-frequency keywords can burst. Add throttling and message grouping.

  • Free Make plans use interval scheduling. Webhooks are not needed here, but cadence affects operation cost.

Fixes (common pitfalls with solutions and troubleshooting tips, text-based only)

  • No messages arrive: Verify chat_id and bot started in the chat. Bots cannot initiate DMs unless the user starts them.

  • 400 Bad Request from Telegram: Escape MarkdownV2 specials. If in doubt, switch parse_mode to HTML and sanitize tags.

  • XML parse fails: Ensure the HTTP response is RSS, not an HTML interstitial. Add a desktop-like User-Agent.

  • Duplicates: Store link in a Data store with a TTL. Check existence before sending.

  • Too many ops: Increase interval to 15 minutes, or filter earlier by tightening the Google News query (use quotes, site:).

  • Old articles surfacing: Add a freshness filter on pubDate.

  • Locale mismatch: Align hl, gl, ceid to your language and region.

Diagram

google-news-alert

Budget calculation

Let:

  • I = scenario interval runs per day.

  • M = matched items per day.

  • Baseline ops per run ≈ 2 (HTTP GET + XML parse).

  • Per match ≈ 2 (Telegram POST + store write).
    Daily ops ≈ 2*I + 2*M.
    Example: 10-minute interval → I = 144. With M = 20, daily ops ≈ 2*144 + 2*20 = 328. Monthly ≈ 9,840. Reduce interval to 15 minutes (I = 96) to save ≈ 1/3 operations, or narrow the query to reduce M.

Future enhancements

  • Batch mode: group all matches from a run into one Telegram message.

  • Multi-keyword routing: send different keywords to different chats using a Router.

  • Smart suppression: ignore repeated sources within a short window.

  • Language filter: reject items where lang does not match target.

  • Summary add-on: call a summarizer for long descriptions and include bullet highlights.

Conclusion

The HTTP + filter pattern is simple and durable. Google News RSS supplies a focused feed. Make handles pull, parse, and match logic. Telegram delivers low-latency alerts. With de-duplication and freshness checks, the system stays precise and low-noise.