> ## Documentation Index
> Fetch the complete documentation index at: https://docs.threadlytics.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Sentiment

## Overview

**Sentiment** classifies each Reddit mention as **Positive**, **Neutral**, or **Negative** based on the language used in the post or comment. This gives you a signal for how Reddit users feel about a topic, not just how often it is being discussed.

## Where It Appears

* **Dashboard** – Sentiment donut chart and Brand Sentiment summary card
* **Sentiment Analysis page** – full breakdown by keyword
* **Conversations page** – per-mention sentiment label and filter
* **Keywords page** – sentiment percentage column per keyword
* **Top Sources page** – average sentiment per user

## How Is It Calculated?

Sentiment is determined by a custom keyword-based engine that runs automatically when a mention is saved.

### Step 1: Normalize the Text

The mention's title and body are combined and converted to lowercase so that "Amazing" and "amazing" are treated identically.

### Step 2: Count Signal Words

The engine scans the normalized text and counts occurrences of words from three predefined signal lists:

| Signal Type            | Example Words                                                                                                               |
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| **Positive**           | amazing, awesome, excellent, fantastic, great, good, love, perfect, wonderful, effective, useful, helpful, easy             |
| **Negative**           | terrible, awful, horrible, bad, worst, hate, disgusting, disappointing, frustrated, useless, broken, bug, error, slow, poor |
| **Question / Neutral** | what, how, why, can, should, suggest, advice, opinion — plus every `?` character in the text                                |

### Step 3: Calculate Ratios

```text theme={null}
totalScore    = positiveCount + negativeCount + questionCount
positiveRatio = positiveCount / totalScore
negativeRatio = negativeCount / totalScore
questionRatio = questionCount / totalScore
```

### Step 4: Classify

The final classification is determined by comparing the ratios:

| Condition                                                              | Classification                     |
| ---------------------------------------------------------------------- | ---------------------------------- |
| `totalScore` is 0 (no signal words found)                              | **Neutral**                        |
| `questionRatio > 0.4` and `positiveRatio == negativeRatio`             | **Neutral**                        |
| Neither positive nor negative ratio exceeds 0.3, or they are too close | **Neutral**                        |
| `positiveRatio > negativeRatio` AND `positiveRatio > 0.3`              | **Positive**                       |
| `negativeRatio > positiveRatio` AND `negativeRatio > 0.3`              | **Negative**                       |
| `questionRatio > 0.4` and `positiveRatio > negativeRatio`              | **Positive** (fixed score of 0.3)  |
| `questionRatio > 0.4` and `negativeRatio > positiveRatio`              | **Negative** (fixed score of -0.3) |

The engine intentionally biases toward **Neutral** when question language dominates. A post asking "What do people think of this tool?" contains positive and negative words but is fundamentally an inquiry, not an opinion. So it is classified as Neutral or weakly positive/negative rather than strongly either way.

### Sentiment Score

In addition to the label, a numeric score is stored ranging from -1.0 to +1.0:

* **Positive score:** `min(positiveRatio - negativeRatio, 1.0)`
* **Negative score:** `max(-(negativeRatio - positiveRatio), -1.0)`
* **Question-dominant score:** capped at ±0.3

This score is used elsewhere in the platform, including opportunity scoring.

## How Sentiment Feeds Opportunity Score

Sentiment is one input into the Opportunity Score (0–100) that rates how worth engaging with a post is:

| Sentiment | Points Added to Opportunity Score |
| --------- | --------------------------------- |
| Positive  | +10 points                        |
| Neutral   | +5 points                         |
| Negative  | 0 points                          |

Other factors (upvotes, comment count) also contribute to the opportunity score.

## Sentiment Aggregates

When sentiment is shown at the keyword or organization level, it is calculated as:

```text theme={null}
positiveMentions / totalMentions × 100 = positive sentiment %
```

This percentage is what appears in the Keywords table's Sentiment column and the Dashboard's Brand Sentiment card.

## Limitations

* The engine relies on a fixed vocabulary of signal words. Slang, sarcasm, and highly domain-specific language may be misclassified
* Very short posts with few words may default to Neutral due to a low `totalScore`
* Sentiment is assigned at index time and is not automatically recalculated if the signal word lists are updated. A keyword reset and re-refresh is required to recompute sentiment for existing mentions.
