---
id: agencias/marca-sentimento-ia
industry: Marketing agencies
usage: specific
effort: medium
grain: Mention or comment; summary by network and topic in 24 and 72 hour windows
---

# Brand and sentiment with AI

What people are saying about the client's brand and its competitors, with every mention classified by AI, the topics that grew in the last 24 hours and an index that does not confuse an AI failure with neutral.

## Executive summary

**For:** Agencies handling clients' brand, content or corporate communications.

**What it solves**

- Every comment and mention gets a sentiment and a topic exactly once, at a controlled cost.
- The sentiment index separates what the AI could not classify.
- The client's leadership only gets topics that truly grew, above a minimum volume.

**Why it matters:** A brand client wants to know what people are saying before it becomes a crisis, not at the end of the month. Classifying by hand does not scale, and a poorly configured AI returns everything as neutral and hides the problem. With fixed rules, the reputation readout comes out every day in the same format and goes into the recurring report.

**Business questions it answers**

- How is the brand's health this week?
- Which negative topics grew in the last 24 hours?
- What is the sentiment index per social network this month?
- Which posts concentrate the negative comments?
- What are competitors advertising right now?

**What you need**

- The client's networks or the social listening tool connected to Nekt
- A language model API key stored in the secrets vault
- The topic list and the sentiment rule agreed with the client

**What you get**

- A mentions table with sentiment, topic and classification date
- Sentiment index and volume per network over 24 and 72 hours, with history
- Rising topics and an executive summary written from the numbers
- An alert when a negative topic grows above the threshold

## Detailed

### The problem

The source delivers free text, often only the current state, and every run brings back comments already seen. Whoever classifies everything again pays several times for the same text; whoever treats an API error as neutral delivers a report with no negatives at all; whoever lets the AI invent topics on every run cannot compare one week with another. And a 100% rise on two mentions becomes a crisis alert.

### Business rules

1. **Classify only what is new.** Use the comment or mention id as the key and classify only ids not yet in the output table, writing by append. In scraped sources without a stable id, the key is client + platform + post + author + reply flag + md5 hash of the text, written by upsert. Reprocess a post only if its comment count grew. (Avoid: Classifying the whole table on every run.)
2. **Failure is not neutral.** API errors, rate limits, responses out of format or outside the list become 'unclassified', to be retried on the next run. Never use neutral as the default value. Call the model with temperature zero and JSON output, and log the first error of each run with the response status and body. (Avoid: Returning 'neutral' when the call fails.)
3. **Sentiment with a written rule.** Positive: praise, thanks, support, approval. Negative: criticism, complaint, negative irony, insult, dissatisfaction. Neutral: question, informational comment, tagging another person with no opinion. Empty text does not go to the AI. The rule lives in the prompt and in the client's context, the same for every run. (Avoid: Asking the model for 'the sentiment' without saying what counts as each.)
4. **Topics from a stable list.** Discovering topics from scratch on every run changes the names and breaks the history. Keep a closed topic list per client in the context, classify each mention into exactly one of them, and let the AI suggest new topics in a separate column for human review. If the call fails, use the default list, never an empty one. (Avoid: Letting the AI invent 5 to 12 new topics on every load.)
5. **Sentiment index only over what was classified.** Index = (positives x 100 + neutrals x 50) / (positives + neutrals + negatives). Unclassified mentions stay out of the denominator and appear alongside, with the classification rate. Compute it per network and in total, over the same window. (Avoid: Dividing by all mentions, with unclassified ones counting as zero.)
6. **Trend with a volume floor.** Compare the last 24 hours with the previous 24 and the last 72 with the previous 72. If both periods have fewer than 5 mentions, the trend is 'insufficient volume'. Up above +15%, down below -15%, stable in between. Highlight at most the 2 rising topics with a dominant negative sentiment, and the 2 positive ones. (Avoid: Alerting a 100% rise on a topic that went from 1 to 2 mentions.)
7. **Window anchored on the latest mention, with freshness.** The 24 and 72 hour windows count back from the source's most recent mention, and that mention's date appears in the result. If the source stopped, the dashboard shows the data is stale instead of saying the brand went quiet. (Avoid: Showing 'last 24 hours' from a source that stopped loading days ago.)
8. **Numbers come from code, text comes from the AI.** Volume, percentages, index and rising topics are computed in code. The executive summary receives those numbers ready and only writes, following the client's style rules. If the writing call fails, save a summary built directly from the numbers. (Avoid: Asking the AI to count mentions and write the summary in one go.)
9. **Competitors through the ad libraries.** To monitor competitors, collect active ads from the Meta Ad Library (by page or search) and the Google Ads Transparency Center (by domain or advertiser), write by upsert with the key client + platform + creative id, and classify the text with one objective question per client (for example, whether the ad is about the topic the client sells). (Avoid: Pasting screenshots of competitors' ads into the report.)
10. **Text assembled, truncated and minimized.** Build the mention text from content, title, caption, description and hashtags, and truncate it to a fixed length before sending (for example, 300 characters for topic and 1,000 for sentiment). Send the model only the text and the id, without the name, profile or contact of whoever wrote it. (Avoid: Sending the source's whole row, with author and profile, to the API.)

### From text to index

Weight of each classification in the 0 to 100 sentiment index.

- **Positive** → Enters the index with weight 100
- **Neutral** → Enters the index with weight 50
- **Negative** → Enters the index with weight 0
- **Unclassified** → Out of the index; retried on the next run
- **Fewer than 5 mentions in both periods** → Insufficient volume, no trend

### Definitions

| Metric | Definition |
|---|---|
| Mention | comment, post or listening occurrence with its own id (or a key from the text hash), counted once |
| Sentiment | positive, neutral, negative or unclassified, assigned once per mention |
| Sentiment index | (positives x 100 + neutrals x 50) / classified mentions in the window, per network or in total |
| Classification rate | classified mentions / mentions in the window |
| 24h change | (mentions in the last 24h - mentions in the previous 24h) / mentions in the previous 24h |
| Trend | up above +15%, down below -15%, stable in between; insufficient volume with fewer than 5 mentions in both periods |
| Dominant sentiment | category with the most mentions of the topic in the 72h window |
| Rising topic | topic with an upward trend in the last 24h, up to 2 per dominant sentiment |

### Pitfalls

- **Brand health all neutral.** The weekly report showed every comment as neutral. The API call was failing and the code returned neutral as the default value. How to avoid: Failures become 'unclassified' and the classification rate shows in the report.
- **A table that would not open between loads.** Files from different syncs had incompatible encodings and the default read of the comments table failed in the notebook. How to avoid: Read file by file, filtering by the cutoff date, when the default read fails.
- **A topic that changed name every day.** The AI discovered topics from scratch on every load and the same theme appeared under different names, with no comparable series. How to avoid: Closed list per client and new suggestions kept apart.
- **Duplicate comments on every scrape.** Profile scraping brought back the same comments on every run, with no stable id, and the count kept growing by itself. How to avoid: Key with the text hash and writes by upsert.
- **An empty scrape reported as success.** The session of the account used for scraping expired without landing on the expected login screen, and the run finished as a success with no new comments. How to avoid: Alert when a successful run brings nothing from a profile that always brings something.
- **A two-mention crisis.** A topic went from 1 to 2 negative mentions and appeared as a 100% rise in the summary for leadership. How to avoid: A floor of 5 mentions before computing a trend.

### Acceptance test

- [ ] Running classification twice in a row creates no new rows and no new API calls.
- [ ] Positives + neutrals + negatives + unclassified = total mentions in the window.
- [ ] The sentiment index recomputed from the counts matches the published one, per network.
- [ ] No topic with fewer than 5 mentions in both periods shows a trend.
- [ ] More than 95% of the window's mentions are classified, or the report shows the incomplete classification warning.

### Context document

```text
Brand and sentiment
- Each mention or comment is classified once: sentiment (positive, neutral, negative, unclassified) and one topic from the client's list.
- 'Unclassified' is an AI failure, not neutral. Report the classification rate alongside any percentage.
- Sentiment index = (positives x 100 + neutrals x 50) / classified. Unclassified excluded.
- Trend: last 24h against the previous 24h and 72h against the previous 72h. Fewer than 5 mentions in both periods = insufficient volume. Up above +15%, down below -15%.
- Windows count back from the most recent mention. State its date.
- Numbers come from the tables. Do not count mentions by reading texts.
- Do not cite the author, profile or contact of whoever commented.
Client exceptions:
- <client>: topics <topic list>; competitors monitored <list of pages or domains>.
- <client>: summary for leadership in paragraphs, no lists, ending with the risk or opportunity reading.
```

### Variations

- **Comments on the client's own posts:** Sentiment of the client's Instagram comments per post, to find the content that draws complaints.
- **Creators and highest-reach posts:** Light sweep of the posts from recent months, selection of those with the most comments and classification of only those, flagging spam and relevant insights.
- **Public reviews:** The same model applied to Google Business Profile reviews, filtered by the client's location.
