# Monitor brand mentions on the web and TikTok

Search the web and TikTok for your brand, then read the comments under the posts that mention it: a daily brand check an agent can run on its own.

Brand monitoring is a loop over the places people talk about you. This recipe covers two of them: the open web, through a web search capability, and TikTok, where it finds the videos that mention your brand and reads the comments under them. Run it daily and let the agent flag what is new or negative.

Each step lists the cheapest tools that serve it, with each one's price and health. Their input fields can differ from one source to the next, so read a tool's schema with `GET /v1/tools/{id}` before you call it, or hand the tools to a model as functions and let it fill them in.

## Steps

### 1. Search the web for mentions

Run a web search for the brand name with words such as review, vs or alternative, and keep the results that are new since the last run.

Platform: [Web search](https://www.orcarouter.ai/tools/web-search.md) · Capability: Web search

No tool serves this step right now.

Example input:

```json
{"query":"\"Notion\" review"}
```

### 2. Find TikTok videos about the brand

Search TikTok videos by the brand name and its product names to catch the posts people are watching.

Platform: [TikTok](https://www.orcarouter.ai/tools/tiktok.md) · Capability: Video search

No tool serves this step right now.

Example input:

```json
{"keyword":"notion app"}
```

### 3. Read the reactions

Pull the comments under the videos that mention the brand and let the agent sort them into praise, complaints and questions that need an answer.

Platform: [TikTok](https://www.orcarouter.ai/tools/tiktok.md) · Capability: Video comments

No tool serves this step right now.

Example input:

```json
{"video_id":"VIDEO_ID_FROM_STEP_2"}
```

## Code

### curl

```shell
# Needs curl and jq. Step 1 is shown; repeat it with each step's query.
TOOL_ID=$(curl -s https://api.orcarouter.ai/v1/tools/discover \
  -H "Authorization: Bearer $ORCAROUTER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"q": "web search", "limit": 1}' | jq -r '.data.results[0].id')

# The inputs the tool takes
curl -s "https://api.orcarouter.ai/v1/tools/$TOOL_ID" \
  -H "Authorization: Bearer $ORCAROUTER_API_KEY" | jq '.data.input_schema'

# Run it with those inputs
curl -s "https://api.orcarouter.ai/v1/tools/$TOOL_ID/run" \
  -H "Authorization: Bearer $ORCAROUTER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"input": {"query": "\"Notion\" review"}}'
```

### Python

```python
# pip install requests openai
import json
import os

import requests
from openai import OpenAI

BASE = "https://api.orcarouter.ai"
KEY = os.environ["ORCAROUTER_API_KEY"]
HEADERS = {"Authorization": f"Bearer {KEY}"}

# One discover query per step of the recipe.
STEPS = ["web search", "tiktok video search", "tiktok video comments"]
TASK = (
    "Find this week's mentions of Notion on the web and on TikTok, "
    "and summarise what people say about it."
)


def discover(query, limit=2):
    r = requests.post(f"{BASE}/v1/tools/discover", json={"q": query, "limit": limit}, headers=HEADERS, timeout=30)
    r.raise_for_status()
    return [tool["id"] for tool in r.json()["data"]["results"]]


def run(name, tool_input):
    r = requests.post(f"{BASE}/v1/tools/{name}/run", json={"input": tool_input}, headers=HEADERS, timeout=120)
    return r.text  # the tool's answer, or its error, goes back to the model


ids = [tool_id for query in STEPS for tool_id in discover(query)]
fns = requests.get(
    f"{BASE}/v1/tools/functions",
    params={"ids": ",".join(ids), "format": "openai"},
    headers=HEADERS,
    timeout=30,
)
fns.raise_for_status()
tools = fns.json()["data"]["tools"]

llm = OpenAI(base_url=f"{BASE}/v1", api_key=KEY)
messages = [{"role": "user", "content": TASK}]
for _ in range(10):
    msg = llm.chat.completions.create(model="openai/gpt-5-mini", messages=messages, tools=tools).choices[0].message
    messages.append(msg)
    if not msg.tool_calls:
        print(msg.content)
        break
    for call in msg.tool_calls:
        result = run(call.function.name, json.loads(call.function.arguments or "{}"))
        messages.append({"role": "tool", "tool_call_id": call.id, "content": result})
```

### TypeScript

```typescript
// npm install openai
import OpenAI from "openai";
import type { ChatCompletionMessageParam } from "openai/resources/chat/completions";

const BASE = "https://api.orcarouter.ai";
const KEY = process.env.ORCAROUTER_API_KEY!;
const headers = { Authorization: `Bearer ${KEY}`, "Content-Type": "application/json" };

// One discover query per step of the recipe.
const STEPS = ["web search", "tiktok video search", "tiktok video comments"];
const TASK =
  "Find this week's mentions of Notion on the web and on TikTok, " +
  "and summarise what people say about it.";

async function discover(q: string, limit = 2): Promise<string[]> {
  const res = await fetch(`${BASE}/v1/tools/discover`, {
    method: "POST",
    headers,
    body: JSON.stringify({ q, limit }),
  });
  if (!res.ok) throw new Error(`discover: HTTP ${res.status}`);
  const { data } = await res.json();
  return data.results.map((tool: { id: string }) => tool.id);
}

async function run(name: string, input: unknown): Promise<string> {
  const res = await fetch(`${BASE}/v1/tools/${name}/run`, {
    method: "POST",
    headers,
    body: JSON.stringify({ input }),
  });
  return res.text(); // the tool's answer, or its error, goes back to the model
}

async function main() {
  const ids = (await Promise.all(STEPS.map((q) => discover(q)))).flat();
  const fns = await fetch(
    `${BASE}/v1/tools/functions?format=openai&ids=${encodeURIComponent(ids.join(","))}`,
    { headers },
  );
  if (!fns.ok) throw new Error(`functions: HTTP ${fns.status}`);
  const { data } = await fns.json();

  const llm = new OpenAI({ baseURL: `${BASE}/v1`, apiKey: KEY });
  const messages: ChatCompletionMessageParam[] = [{ role: "user", content: TASK }];
  for (let turn = 0; turn < 10; turn++) {
    const reply = await llm.chat.completions.create({ model: "openai/gpt-5-mini", messages, tools: data.tools });
    const msg = reply.choices[0].message;
    messages.push(msg);
    if (!msg.tool_calls?.length) {
      console.log(msg.content);
      return;
    }
    for (const call of msg.tool_calls) {
      const fn = call.type === "function" ? call.function : undefined;
      const result = fn ? await run(fn.name, JSON.parse(fn.arguments || "{}")) : "unsupported tool call";
      messages.push({ role: "tool", tool_call_id: call.id, content: result });
    }
  }
}

main();
```

## Related recipes

- [Track competitor TikTok accounts](https://www.orcarouter.ai/tools/recipes/track-competitor-tiktok-accounts.md): Pull each competitor's TikTok profile, find its latest videos and read what viewers say, in three tool calls an agent can repeat every week.
- [Enrich a lead list](https://www.orcarouter.ai/tools/recipes/enrich-a-lead-list.md): Turn a list of company domains into firmographics, a contact's work email and a recent news hook, with one API key.
- [Find contact emails for a list of domains](https://www.orcarouter.ai/tools/recipes/find-contact-emails-for-domains.md): Go from a bare domain to the right person's work email: confirm the company, find who holds the role and look up the address.

---

Markdown version of https://www.orcarouter.ai/tools/recipes/monitor-brand-mentions
