What this actually watches
I called it UAE partnership monitoring, but it's actually kind of like monitoring any relationships going on with the UAE government and other governments or other organizations, anything like this.
Sales found out after the fact, or never
This came up from the pain point of sales leadership: sometimes we get to know there's some talk going on. I think it's something along the lines of an MoU signed or some other talking going on.
We realize that, because we have less of a footprint in terms of sales, our bigger competitors are already talking to them, already have engagements, and it's difficult for us to engage in a meaningful way.
I was in the discussion with them, and it would be good to know something in advance. I said, "Let me explore. I have some ideas."
I reused what already works
This is what I created, so I'm not doing everything from scratch. I'm reusing something which is already working. For instance, Google Alerts is very good for going through anything that gets mentioned.
I came up with the names you can see in Google Sheets for all senior people and influential government figures and sheikhs inside the UAE. I took the names down.
The list is grouped the way the government is: federal leadership and the core Cabinet, a foreign affairs cluster, trade and the newer portfolios worth watching, Abu Dhabi royal leadership and deputy rulers, Abu Dhabi senior officials, and the Dubai Executive Council. Every name carries its own query, pairing the ways that person is written about with the words that mean something is happening. Alongside it sits a second list of 24 government entities. Each one carries its base URL, its news listing, and whether it offers RSS, a sitemap or a search. The last column says which of those to prefer.
Originally I had them under my own email, but that stopped working because of authentication. I created a free email dedicated just for this, so I fixed that problem.
The two lists it runs on
Two ways in
I had to do it in two ways: prefill what already exists, and set it up so we can pick up any future mentions.
Mapping where the doors already are
Another actual reason why I ended up doing this whole thing was that we wanted to map strategically for our go-to-market based on where government already has existing relationships. Using our relationships and being plugged in, we can open the doors. That's another way for us to see which countries and which projects would be beneficial for us to monitor, track, and have a positive signal.
Filling in what already happened
Now, moving to prefilling, I had two workflows on n8n. One was using Perplexity mostly as a main source of raw information.
Which I triggered from a Google Sheet. I did research with Perplexity. I converted everything using OpenAI models to JSON. I split it and normalized it, and after that I scraped every single article and processed this by analyzing each article and updating it into the sheet.
If it failed, I just did nothing because it was enough to go through, so I didn't need to solve it for every single one, even if it had some bot protection. I used the simple tool, nothing complex, just to simplify. Otherwise, I would have to do it with more robust body detection, but I chose just a simple HTML scraper, which is native on n8n.
What that looks like underneath:
- The trigger is a checkbox. Ticking "Start AI Research" against a government entity posts that row to an n8n webhook. The list of what to research and the button that runs it are the same object.
- Perplexity runs on sonar-deep-research. It asks for official announcements from the last 365 days that name a non-UAE country next to a word meaning something happened: met with, held talks, hosted, delegation visit, joint statement, MoU, agreement, signed.
- GPT-5.2 turns the reply into structured JSON, then every article is fetched one at a time, 3 seconds apart, with a 60 second timeout.
- Anything on wam.ae, the state news agency, returns headers n8n cannot parse, so those URLs go through a reader proxy instead of being fetched directly.
- A failed fetch still writes its row, with the reason classified: blocked by a firewall, headers the parser choked on, or the status it came back with. What could not be read is a filter away rather than lost.
The hourly monitor
The other one was slightly different. The trigger was Google Alerts email, and I processed this: a monitoring email for new emails coming in every hour.
What I'm doing is just processing this as a raw email:
- Extracting links
- Checking existing links
- Splitting
- Filtering for new URLs
- After that, scraping
- If it fails, recording
- If it doesn't fail, taking them through the loop and analyzing those Google Alerts for each scraped website
- Flattening the results
- Updating or adding the signal
- If it reaches our threshold, sending the Slack alert notification
The parts that needed real work:
- Pulling the links is its own model call, because a Google Alerts digest is not a tidy document. It has to tell a daily digest from a single alert, map every link back to the query that found it, and unwrap the Google redirect to reach the real destination. Then it throws away the furniture: unsubscribe links, full-coverage links, images, social profiles.
- Before the analyzer sees a page it is stripped of scripts, styles, comments and embedded images. Then it is capped at 180,000 characters: the first 130,000 plus the last 50,000, because a long page buries the announcement at one end or the other.
- GPT-5.5 returns one structured record: who met whom, which countries, what kind of instrument, the named people on both sides, a proof excerpt, a confidence and a score. It is told never to invent a fact, a date, a name or a country, and to return null rather than guess.
- Every record carries a fingerprint built from the URL, the people, the countries, the interaction type and the date. So the same meeting reported by three outlets collapses into one signal.
The rule the whole thing turns on is what counts as eligible. The default is that a non-UAE country has to be named explicitly, and a region does not count: Asia is not a country. But there is a second door. A UAE-only announcement still qualifies on three conditions. It has to be a government-led strategic initiative. It has to carry a concrete delivery signal that implies real budget: a named programme, an investment figure, a rollout timeline or a procurement step. And it has to touch something we could sell into. So the monitor catches DIEZ launching District IO and Block 14 on AED 11bn and AED 1.8bn. It catches the Suqia water award opening a $1 million cycle around digital transformation. Neither involves a foreign government at all.
The alert does not fire on the score. The score sets the priority label inside the message. What decides whether Slack hears about it is whether the analyzer marked the record validated. That needs a named country or a qualifying domestic programme, a real delivery mechanism, and no downgrade for being ceremonial. Everything else lands in the sheet and waits. That is the point: an alert channel that fires on everything gets muted in a week.
Once the alerts were set up and I activated it, it started to run the next day. I just needed to do a few manual triggers to test everything.
What did not work was the first version of the dedupe. It looked like it was working and was quietly doing nothing. It checked each URL against the sheet one at a time. On a real Google Alerts digest it dropped every new URL, because the lookup only ever returned rows that were already there. It passed every test I ran, because I was testing one item at a time and n8n was filling the empty result for me. Only a real digest exposed it. At some point it died, so I needed to redo it. I fixed it using Claude Code, rebuilt that half to read the whole sheet once and filter in code, and made it more robust.
The principle underneath is that an alert is only worth building if it can say no. Anything can watch a keyword. The work is in the rules that throw things away: a region is not a country, a ceremonial meeting is not an engagement, a courtesy visit with no next step is not a signal. A channel that fires on everything gets muted in a week, and a muted channel is worth less than no channel, because everyone still believes it is working.
The alerts the team actually gets