On this page
Build a Free Adverse Media Monitor with Webz.io News API and Google Apps Script

Build a Free Adverse Media Monitor with Webz.io News API and Google Apps Script

Build a Free Adverse Media Monitor with Webz.io News API and Google Apps Script

You can build a useful adverse-media monitoring service without running a server, maintaining your own news crawler, or paying for separate monitoring software.

This tutorial uses:

  • Webz.io News API to search and classify news
  • Google Sheets to maintain the watchlist and store matches
  • Google Apps Script to run the monitor
  • Email for alerts
  • Google Apps Script triggers to run it automatically

Webz.io’s Free plan includes $5 in API credits every month, so you can build and run a small monitor without paying for API access.

The workflow is simple:

Targets in Google Sheets
        ↓
Google Apps Script
        ↓
Webz.io News API
        ↓
Target name
+ negative sentiment
+ adverse category/topics
        ↓
Remove articles already seen
        ↓
Save results to Google Sheets
        ↓
Send an email digest

1. How to search for adverse media

The first part of the query is simply the company or person’s name.

For example:

"Acme Corp"

Then add Webz.io’s sentiment filter:

sentiment:negative

And an adverse-news category:

category:"Crime, Law and Justice"

The complete query is:

"Acme Corp"
AND sentiment:negative
AND category:"Crime, Law and Justice"

Webz.io supports free-text queries, quoted phrases, Boolean operators, sentiment, categories, topics, entities, source filters and other structured filters inside the q parameter.

Using Webz.io’s classification means you don’t have to maintain a long query such as:

fraud OR bribery OR corruption OR arrested
OR investigation OR lawsuit OR ransomware ...

Instead, Webz.io classifies the articles for you.

2. Use topics when you want more precision

Crime, Law and Justice is intentionally broad.

Webz.io also classifies news into hundreds of more specific topics. The current API supports 629 IPTC-derived topics.

For adverse media, useful topics include:

fraud
corruption
corporate crime
cyber crime
data breach
arrest
investigation (criminal)

A narrower query might therefore be:

"Acme Corp"
AND sentiment:negative
AND (
    topic:fraud
    OR topic:corruption
    OR topic:"corporate crime"
    OR topic:"cyber crime"
    OR topic:"data breach"
    OR topic:arrest
    OR topic:"investigation (criminal)"
)

Values containing spaces need quotation marks. Category and topic values are case-insensitive.

I recommend starting with:

category:"Crime, Law and Justice"

Then look at which topics appear in your results. You can narrow the query later if the category produces too much noise.

3. Don’t use organization: or person: unless you need them

For most targets, use a normal quoted phrase:

"Acme Corp"

or:

"Jane Smith"

There is no need to classify every watchlist entry as a person or organization.

Entity filters become useful when a name is ambiguous.

For example:

organization:"Apple"

can help distinguish Apple Inc. from articles discussing apples generally.

For a common person’s name, you could instead add context:

"John Smith" AND "Acme Corp"

Webz.io supports person: and organization: filters, as well as entity-level sentiment filters such as organization.negative:. Entity extraction is currently available for English, German, Spanish and Italian.

We’ll therefore make entity filtering optional.

4. Create the Google Sheet

Create a new Google Sheet called:

Adverse Media Monitor

Then open:

Extensions → Apps Script

The Apps Script project will be attached to the spreadsheet.

You don’t need to create the spreadsheet tabs manually. The setup script below will create them.

5. Get your Webz.io API token

Create or log into your Webz.io account and get your API token.

The standard News API endpoint is:

https://api.webz.io/api/news

A basic request looks like:

https://api.webz.io/api/news?token=YOUR_TOKEN&q="Acme Corp"

The News API returns structured news articles in a posts array, including fields such as title, text, URL, publication time, crawl time, sentiment, categories, topics and source metadata.

We’re using the regular Webz.io News API, not News API Lite.

6. Add your settings to Apps Script

In Apps Script, open:

Project Settings
→ Script Properties

Create:

WEBZ_TOKEN

and enter your Webz.io API token.

Then create:

ALERT_EMAIL

and enter the email address where alerts should be sent.

This keeps the token outside the source code.

7. Add the monitoring code

Delete the default Apps Script code and paste the code in the following link.

Google Apps Script’s UrlFetchApp supports HTTP requests, MailApp can send email, and ClockTriggerBuilder.everyHours() can create recurring time-based triggers. The script also uses LockService to prevent two executions from updating the Sheet simultaneously.

8. Run the setup

Select:

setup

in the Apps Script editor and click Run.

Google will ask you to authorize the script.

The script creates two sheets:

Targets
Results

The Targets sheet looks like this:

Enabled Name Query override (optional) Last checked
TRUE Acme Corp
TRUE Example Holdings
TRUE Apple organization:”Apple”
TRUE John Smith “John Smith” AND “Acme Corp”

For most targets, leave Query override blank.

For Acme Corp, the script automatically creates:

"Acme Corp"
AND sentiment:negative
AND category:"Crime, Law and Justice"

Only use the override column when the name needs additional context.

9. Test the monitor

Run:

monitorAdverseMedia

The first search checks the previous 24 hours.

Matches are added to the Results sheet with:

Target
Title
URL
Publication time
Crawl time
Source
Sentiment
Categories
Topics
UUID

Webz.io provides a unique uuid for each post. The script stores it so the same article is not reported repeatedly for the same target.

A result might look like:

Target:
Acme Corp

Title:
Regulators investigate Acme Corp over alleged misconduct

Sentiment:
negative

Categories:
Crime, Law and Justice

Topics:
Crime, Law and Justice->investigation (criminal)
Crime, Law and Justice->corporate crime

10. How the monitor finds only new articles

The script maintains a Last checked timestamp for every target.

Webz.io’s ts parameter accepts a Unix timestamp in milliseconds and returns posts crawled at or after that timestamp.

Suppose the monitor runs at:

06:00

and then again at:

12:00

The second run searches from approximately 06:00 onward.

The timestamp represents crawl time, not the article’s publication time.

That distinction matters. A newspaper might publish an article at 05:50, but Webz.io may discover it at 06:10. Monitoring by crawl time makes sure the article is still picked up.

The script deliberately stores the time when each run started, rather than when it finished. This creates a small overlap between searches.

Duplicates created by that overlap are removed using the Webz.io UUID.

This is safer than leaving a gap between runs.

11. Pagination

A query can return more articles than fit in one response.

Webz.io returns:

posts
more_results_available
next

When next is available, the script follows that URL until there are no additional results.

Webz.io specifically recommends using the supplied pagination cursor instead of constructing pagination parameters yourself.

The script also waits 1.1 seconds between pages because Webz.io normally limits tokens to roughly one API request per second.

This is important for monitoring. Stopping after an arbitrary number of pages can cause articles to be skipped during a busy news cycle.

12. Run it automatically

Once manual monitoring works, run:

createTrigger

once.

This creates an Apps Script trigger that runs:

every 6 hours

Your computer does not need to be running.

Google Apps Script executes the monitor in Google’s infrastructure. everyHours(6) is supported directly by Apps Script’s time-based trigger API.

For a small watchlist, six hours is a reasonable starting point.

If you need faster alerts, you can increase the frequency. If you are monitoring many targets, reduce the frequency or group targets into queries to conserve API credits.

13. Switch from categories to topics

Once you have collected some results, look at the Topics column.

If the broad category returns too many irrelevant stories, change:

ADVERSE_FILTER:
  'category:"Crime, Law and Justice"'

to:

ADVERSE_FILTER:
  '(' +
    'topic:fraud' +
    ' OR topic:corruption' +
    ' OR topic:"corporate crime"' +
    ' OR topic:"cyber crime"' +
    ' OR topic:"data breach"' +
    ' OR topic:arrest' +
    ' OR topic:"investigation (criminal)"' +
  ')'

Now the monitor searches:

"Acme Corp"
AND sentiment:negative
AND (
    topic:fraud
    OR topic:corruption
    OR topic:"corporate crime"
    OR topic:"cyber crime"
    OR topic:"data breach"
    OR topic:arrest
    OR topic:"investigation (criminal)"
)

This is usually easier to maintain than building your own adverse-media dictionary.

14. Expand the definition of adverse media

Not every adverse event belongs under crime.

Depending on what you’re monitoring, you may also care about issues such as:

economic sanctions
business restructuring
layoffs
workplace health and safety
sexual misconduct

Webz.io topics span all 17 top-level categories, so the same approach can be extended to vendor risk, reputational risk, ESG monitoring and other due-diligence use cases.

For example:

ADVERSE_FILTER:
  '(' +
    'category:"Crime, Law and Justice"' +
    ' OR topic:"economic sanction"' +
    ' OR topic:"workplace health and safety"' +
    ' OR topic:"sexual misconduct"' +
  ')'

15. Keep an eye on API usage

The standard Webz.io APIs use a credit model.

The current Free plan gives you $5 of free API credits every month, making it possible to build and operate a small monitor without paying.

Queries over recent data use the lowest-cost search window. Searching deeper into history consumes more API credits: Webz.io currently documents higher credit consumption for requests going more than 31 days into the past.

For monitoring, this isn’t usually necessary.

The script searches only since the previous execution, so nearly every request concerns very recent data.

That keeps both latency and API consumption low.

16. An adverse-media match is not proof of wrongdoing

There is one limitation you should keep in mind.

An article such as:

Acme Corp helps police investigate major fraud

could still match:

"Acme Corp"
AND sentiment:negative
AND topic:fraud

Acme Corp is mentioned in an adverse story, but it may be the victim rather than the accused party.

Likewise:

Acme Corp cleared after corruption investigation

may still have negative sentiment and a corruption-related topic.

So this service should be treated as a screening system:

Webz.io News API
        ↓
Negative + adverse category/topic
        ↓
Google Sheet
        ↓
Human review
        ↓
Relevant / not relevant

The automated search identifies articles worth reviewing. It should not, by itself, be used to conclude that a company or person committed wrongdoing.

The finished system

You now have an automated adverse-media monitor built entirely with Webz.io and free Google tools:

Google Sheets watchlist
        ↓
Google Apps Script
        ↓
Webz.io News API
        ↓
"Target name"
AND sentiment:negative
AND adverse category/topics
        ↓
Deduplicate using UUID
        ↓
Google Sheets results
        ↓
Email digest

Start with the simplest query:

"COMPANY OR PERSON NAME"
AND sentiment:negative
AND category:"Crime, Law and Justice"

Use organization:, person: or additional context only when the target name is ambiguous.

Then use the categories and topics returned by Webz.io to make the monitor more precise over time.

Because Webz.io now provides $5 in free API credits every month, the standard News API is enough to build and operate a small adverse-media monitoring service without needing a separate free or limited API product.

Subscribe to our blog for more news and updates!

By submitting you agree to Webz.io's Privacy Policy and further marketing communications.

Footer Background Large
Footer Background Small

Power AI with Web Data

icon

Ready to Explore Web Data at Scale?

Speak with a data expert to learn more about Webz.io’s solutions
Speak with a data expert to learn more about Webz.io’s solutions
Create your API account and get instant access to millions of web sources
Create your API account and get instant access to millions of web sources