MCP App Store
by KeenEthics

Overview

Monitor and analyze your brand's visibility across AI search engines. Track your visibility, sentiment, and share of voice and compare to competitors.

Tools

archive_prompts

ChatGPT
Archive up to 50 prompts (sets is_archived = true) so they stop running while keeping their chats and history intact. Prefer this over delete_prompts when the data should be retained. Returns a count of archived prompts plus any skipped (not found) or rejected items. Confirm with the user before calling.

assign_domain_classification

ChatGPT
Assign a built-in classification (Corporate, Competitor, Editorial, Institutional, Other, Reference, UGC, You, Related) or the name of a custom domain classification to a domain. Overrides any heuristic classification. The override applies to the whole root domain, including its subdomains. If the name you pass matches an existing custom classification, the custom one is used — to force a built-in with the same name, pass its enum value (e.g. "OTHER"). Confirm with the user before calling. Returns { success: true } once the override is saved.

assign_url_classification

ChatGPT
Assign a built-in classification (Homepage, Category Page, Product Page, Listicle, Comparison, Profile, Alternative, Discussion, How-To Guide, Article, Review, Other) or the name of a custom URL classification to a URL. Overrides any heuristic classification. The override applies to the URL in its normalized form, so it matches the same page regardless of trailing slashes, query-parameter order, or http/https scheme. If the name you pass matches an existing custom classification, the custom one is used — to force a built-in with the same name, pass its enum value (e.g. "OTHER"). Confirm with the user before calling. Returns { success: true } once the override is saved.

create_actions

ChatGPT
Write up to 50 actions of the customer's own in one call, so work Peec did not suggest is tracked beside the work it did — same list, same statuses, same filters. This is for work the customer has decided to do. It does not itself change what the engines say, and writing an action does not make Peec do anything: the steps are the customer's to carry out. kind decides the action's type and group, which is what files it beside the generated ones, and steps is the work to do — a step naming a section is grouped under that heading. Write every step field in English regardless of the conversation language: the section heading (section), step title and step description. A topic or prompt the project does not hold rejects that item alone. Returns the created actions with their new ids, plus any rejected items. Confirm the wording with the user before calling.

create_brand_perception_attribute_clusters

ChatGPT
Add custom attributes to the brand-perception Market view — the same edit the Add attribute button next to Manage attributes makes. Use it when the user wants to track a quality AI is not yet measured on, or asks whether they can add their own attribute: they can, and this is how. Each new attribute starts with no terms under it. A run is queued for the batch, so its market prominence scores appear within a few minutes rather than on the next scheduled run; do not report scores for it until a later read returns them. Names are matched case-insensitively against the project's existing attributes: one that already exists comes back under skipped instead of being added. A project holds at most 10 custom attributes, and a call that would exceed that adds nothing and returns an error naming the limit. This is not the tool for renaming or merging attributes, or for moving a term between them; that is edit_brand_perception_attribute_clusters. Confirm the exact names with the user before calling. Returns created (each with its cluster_id and name) and skipped (name and reason) when any were skipped. Verify with list_brand_perception_attribute_clusters afterwards: the new attributes are listed with is_custom true.

create_brands

ChatGPT
Create up to 50 brands (competitors or own) in a project in one call. Returns the created brands with their new ids, plus any skipped items. After creation, call list_brands to confirm the requested brands exist before reporting success, even when they appear in this tool's created list. Duplicates are matched case-insensitively on name. A project can track at most 200 brands total (own + competitors); a call that would exceed this fails.

create_categories

ChatGPT
Create product categories. Each item needs a name and an optional parent_id — omit it for a top-level category, or pass another category's id (use list_categories to find it) to nest it underneath. A name must be unique among its siblings. Items apply in order. Returns per-item results { created, rejected } — the batch never fails as a whole. Rejection reasons: parent_not_found, name_conflict. Confirm with the user before calling — this mutates project data.

create_domain_classification

ChatGPT
Define a new custom domain classification on a project. This creates the classification entity — it does not assign it to any domain (use assign_domain_classification for that). Confirm with the user before calling. Returns the created classification as { name, color }.

create_facts

ChatGPT
Add up to 50 manual facts for a project in one call. Each fact is a statement about the brand that Peec will use to check claims found in future AI answers. Returns every created fact with its new id. Confirm the exact statements with the user before calling because this mutates shared project data.

create_global_brand

ChatGPT
Create a brand and return its global_brand_id. Use this when list_global_brands finds no match for a brand you need, or when create_products rejects an item with brand_not_found. Returns { id, name }. The returned name is the brand's canonical name and may differ slightly from the name you sent. This is separate from create_brands, which creates brands a project tracks for AI-visibility reporting; the two have different ids and are not interchangeable. Confirm with the user before calling — this creates a brand.

create_products

ChatGPT
Create catalog products (source=CATALOG) in a project — the brand's own claimed/uploaded products, as opposed to LLM products that Peec auto-detects in shopping answers. Each item needs a global_brand_id (use list_global_brands to find it by name, or create_global_brand if the brand doesn't exist yet) and a name unique within that brand; description, image_url, per-currency price_override, and category_ids (use list_categories to find category ids) are optional. When products need new categories, build the category tree first with create_categories (parent_id nests, omit for top-level), then pass the returned category_ids here. Returns per-item results { created, rejected } — the batch never fails as a whole. Rejection reasons: name_conflict (name already used in the brand), brand_not_found, category_not_found. Confirm with the user before calling — this mutates project data.

create_projects

ChatGPT
Create up to 50 projects in the user's company in one call, under the same plan limits and credit pool as creating them in the app. Never assume a project's domain or its allocated_credits: you may suggest values, but confirm each one with the user before calling. Returns the created projects with their new ids, plus any rejected with the reason. A new project starts with no brands or prompts; they are added in that project with create_brands (including the own brand) and create_prompts. Every project except an onboarding one (the first project of a company with no plan yet) needs allocated_credits from the company's unallocated credits; a paying company's first project needs them too. Agency and partner companies can also create pitch projects with is_pitch: those omit allocated_credits and model_channel_ids entirely and run under the company's pitch limits.

create_prompts

ChatGPT
Create up to 50 prompts in a project in one call. Returns the created prompts with their new ids, plus any skipped/rejected items. Every prompt needs a topic: pick the best-fitting existing topic, or create one with create_topics first. Accepts existing topic_id and tag_ids only — this tool does not auto-create topics or tags. Confirm with the user before calling — this mutates project data and may consume plan credits.

create_source_tags

ChatGPT
Create up to 50 tags for URLs and domains (source tags) in one call. Use these for labels that are not a page or website type, such as ownership, business role, monetization or a campaign. Returns the created tags with their new ids, plus any skipped items. Names are unique per project, matched case-insensitively. To create prompt tags use create_tags instead.

create_tags

ChatGPT
Create up to 50 tags in a project in one call. Each tag may specify a group (grouped tags share the group's color, so their color field is ignored). Returns the created tags with their new ids, plus any skipped items. Duplicates are matched case-insensitively on name.

create_topics

ChatGPT
Create up to 50 topics in a project in one call. Topics group related prompts. Returns the created topics with their new ids, plus any skipped/rejected items. Duplicates are matched case-insensitively on name. Items beyond the project's topic limit land in rejected.

create_url_classification

ChatGPT
Define a new custom URL classification on a project. This creates the classification entity — it does not assign it to any URL (use assign_url_classification for that). Returns the created classification's name, which is what you pass to assign_url_classification. Confirm with the user before calling.

delete_actions

ChatGPT
Remove up to 50 actions the customer wrote themselves. The removal is permanent and there is nothing to restore from, so confirm with the user before calling. An action Peec generated cannot be removed here and comes back skipped, exactly as a missing one does: decline it with update_actions_status instead, which keeps a record of what was suggested and turned down. Returns a count of deleted actions plus any skipped.

delete_agent_schedules

ChatGPT
Delete up to 50 of the user's agent schedules in a project. Returns a count of deleted schedules plus any skipped (not found) ids. This is destructive — always confirm with the user before calling.

delete_brands

ChatGPT
Delete up to 50 brands in a project. Returns a count of deleted brands plus any skipped items (successful items are not echoed back). This is destructive — always confirm with the user before calling.

delete_categories

ChatGPT
Delete categories by id (use list_categories to resolve ids). A deleted category's child categories and products move up to its parent (a top-level delete sends children to the top level and its products to Uncategorized). Returns per-item results { deleted, rejected } — the batch never fails as a whole. Rejection reasons: not_found, name_conflict (a child being moved up would clash with an existing sibling name). Confirm with the user before calling — this mutates project data.

delete_domain_classification

ChatGPT
Permanently delete a custom domain classification entity. Cascades through the override table — any domains currently assigned this classification fall back to their heuristic classification. To only clear a single domain's assignment, use unassign_domain_classification instead. This is destructive — always confirm with the user before calling. Returns { success: true } once deleted.

delete_facts

ChatGPT
Soft-delete up to 50 facts in one call. Deleted facts disappear from the fact list and are excluded from future fact-checking; historical verdicts keep their original fact versions. Returns a deleted count plus skipped items. Call list_facts first, show the user the exact statements, and get confirmation before calling because deletion cannot be undone in the Peec app.

delete_products

ChatGPT
Delete products by id (use list_products to resolve ids). Returns per-item results { deleted, skipped } — ids not present in the project are skipped (not_found). Only delete source=CATALOG products. Deleting LLM-source products is futile — the ingestion pipeline re-creates an LLM product whenever a shopping answer mentions it again. Confirm with the user before calling — this mutates project data.

delete_prompts

ChatGPT
Delete up to 50 prompts in a project. Deletions run asynchronously — returns a count of queued deletions plus any skipped (not found / already deleted) or rejected items (queued items are not echoed back). This is destructive — always confirm with the user before calling.

delete_source_tags

ChatGPT
Delete up to 50 source tags. Each deleted tag is removed from every URL and domain that carries it. Returns a count of deleted tags plus any skipped items. This is destructive — always confirm with the user before calling.

delete_tag_groups

ChatGPT
Delete up to 50 user-defined tag groups. By default each group's tags are kept and simply ungrouped; set delete_tags=true on a group to delete its tags and remove them from every prompt. Returns each group with its affected tag count, plus any skipped (not found) or rejected items. This can be destructive — confirm with the user before calling.

delete_tags

ChatGPT
Delete up to 50 tags in a project. Removes tag associations from prompts. Returns a count of deleted tags plus any skipped items (successful items are not echoed back). This is destructive — always confirm with the user before calling.

delete_topics

ChatGPT
Delete up to 50 topics in a project. Detaches associated prompts (prompts are kept) and deletes any prompt suggestions linked to the topics. Returns a count of deleted topics plus any skipped items (successful items are not echoed back). This is destructive — always confirm with the user before calling.

delete_url_classification

ChatGPT
Permanently delete a custom URL classification entity. Any URLs currently assigned this classification fall back to their heuristic (default) classification. To only clear a single URL's assignment, use unassign_url_classification instead. This is destructive — always confirm with the user before calling. Returns { success: true } once deleted.

edit_brand_perception_attribute_clusters

ChatGPT
Rename and delete brand-perception attributes, move terms between attributes and unassign terms from theirs — the same edits the Manage attributes screen makes. An attribute is a grouping the Market view scores; a term is a raw phrasing extracted from AI answers that sits under one. Use those two words with the user: the arguments say cluster_id and attribute for historical reasons, but the user never sees them. Resolve every cluster_id and term with list_brand_perception_attribute_clusters first; both must be copied verbatim. To add a new attribute use create_brand_perception_attribute_clusters instead. Pass any combination of renames, delete_cluster_ids, unassign_terms and reassignments; at least one is required. The whole call is one transaction — if any edit is rejected nothing is applied — and edits run in the order reassign, rename, unassign_terms, delete_cluster_ids however they are listed. So merging two attributes is one call: move every term out of the losing attribute and delete it. Neither deleting an attribute nor unassign_terms permanently removes a term — both unassign it, so it stays visible under unassigned and can be moved into an attribute later. Scores re-aggregate on the next read, so the change is immediate and needs no new scraping run. It rewrites a taxonomy the whole project shares. A rename, a moved term or an unassignment can be undone by repeating the edit in reverse; deleting an attribute cannot — the attribute itself is gone for good, though its terms are not, since they survive as unassigned and can be moved into another attribute. Show the user the exact edits and get their confirmation before calling. Name each term and each attribute at most once per call; repeating one is rejected because the two edits would race. Returns the counts applied. Errors: invalid (a repeated target), not found (unknown attribute or term), conflict (a new name collides with another attribute).

edit_optimize_content

ChatGPT
Rewrite passages of the article behind a content-optimisation action, up to 50 in one call (target 40 or fewer). Read the article with get_optimize_content first — each original_text is a passage quoted from it word for word, and that quote is how the passage is found. Quote a whole passage, not a fragment: the article is edited a paragraph or heading at a time, and a quote spanning two of them matches nothing. new_text is the replacement as markdown and cannot be empty — this rewrites a passage and cannot delete one. Asked to cut something, rewrite the passage without it, or say that removing it is an edit the user makes themselves. Every edit lands in one revision, so the call applies as a whole and the article's version moves once. Nothing is written unless all of them can be: a quote matching no passage, matching more than one, or naming a passage another edit in the same call already targets is an error for the whole batch. Which tool does what to a suggestion depends on its kind, from get_optimize_content: - rewrite — it carries the wording already. Accept or dismiss it with resolve_optimize_content_suggestions. Not yours to retype. - edit — it only names what is missing, so putting it in the article means writing the words. That is this tool: rewrite the passage it concerns and set carries_out_suggestion_id to its id, which marks it accepted in the same revision so it stops reading as outstanding. Accepting it on its own would tick it off without changing a word. Asked to apply every suggestion, do both halves: resolve_optimize_content_suggestions to accept the rewrite ones, and this tool for the edit ones, each carrying its id. Asked about a single suggestion, take whichever of those two paths its kind calls for. The changes land as tracked edits under the user's name, which they can revert on the Optimize content screen exactly like ones they typed. A passage you have already edited can be edited again: quote its current wording. An edit whose quote no longer matches the article is rejected rather than applied over, so re-read with get_optimize_content after a rejection instead of retrying the same call. This rewrites the customer's live article, so name the passages you are about to change in the sentence before you call it. Change only what they asked for, and say what you changed rather than pasting the new wording for them to copy.

finalize_prompt_suggestions

ChatGPT
Resolve prompt suggestions listed by list_prompt_suggestions, in one pass over a reviewed set: ids in accepted_ids become tracked prompts and promote their topics into the project, ids in rejected_ids are deleted from the review list. Pass either or both, up to 50 ids in total. Rejecting never touches tracked prompts, since a suggestion has produced none until accepted; a topic left with no suggestions is cleared with them. The accepted set is checked against the project's remaining prompt allowance as a whole and refused as a batch when it does not fit — trim it and retry rather than splitting across calls, and note that a refused accept also leaves the rejections unapplied. Returns a count per outcome, any ids that matched no suggestion, and any allowance warning. Confirm with the user before calling.

generate_prompt_suggestions

ChatGPT
Generate prompt suggestions for a project — the same generation Prompt discovery runs in the app. Generation runs in the background: the call returns {queued: true, generation_id}, which get_prompt_suggestion_generation reads until the run succeeds or fails. List successful results with list_prompt_suggestions, then accept or reject them with finalize_prompt_suggestions. topic_id, prompt_suggestion_id and segment each narrow the run and are mutually exclusive; with none of them, every topic awaiting review is generated for again, replacing its current suggestions — pass a scope unless the user asked for a full refresh. Requires the project's prompt_builder.distribution (branding/intent split), set via set_project_profile. Markets are optional: without them the project's own country and language are used. Spends one of the project's hourly prompt generations, so never call it in a loop. Confirm with the user before calling.

generate_topics

ChatGPT
Compose candidate topics for the project from its brand profile — the same composition Prompt discovery runs in the app. Nothing is saved: review the returned names with the user and create the chosen ones with create_topics. Composition already accounts for the project's existing topics, so it proposes only what fills a gap and can return an empty list when the set is already well covered. Requires the project profile to name products and services (set via set_project_profile). Spends one of the project's hourly topic generations, so never call it in a loop. Returns {topics: [name, ...]}.

get_action

ChatGPT
Read one action by an id from list_actions: what to do, the content brief when there is one, and the competitor demand behind it. Everything list_actions returns is here too. Always returned: title, description (the case for the action, with its sources), the authoring fields the customer owns — kind (what they wrote it as, null on a generated action), notes, page_url, priority, assignee_user_id, due_on, tag_ids, repeat, time_range, language_codes — content_brief_outline (content briefs only — the headline options, meta title and description, the brand's angle and the facts it may claim, the points to cover, and the whole brief as one markdown document), and opportunity (the competitor demand a brief answers, also briefs only). A site audit action — SEO_ISSUE or ROBOTS_TXT — carries neither, and its description and steps are the whole fix. An SEO_ISSUE in the crawlability category means Peec's own audit crawler could not read the site, which pauses Peec's page-level recommendations for it; it says nothing about whether AI engines can reach the site, so never present it as a cause of changes in retrieval or citation. ROBOTS_TXT is the action about AI crawlers. Opt in via fields, default none: - steps — on a template action, the work itself: each step holds one or more options, and an option is a concrete edit with the text to use. On a content brief they are instead the material the brief was written from, labelled by gap_type — the fan-out prompts, what communities say, and the sources winning the topic today. - outline_points — the content brief section by section: what each one argues, the questions it answers and the evidence behind it. - impacted_prompts — the prompts this action affects. On source-correction actions, own_coverage_score is the owned domains' share of all citations for that prompt in the action's analysis window; other types use their documented page-coverage score. - ngrams — terms competitors use on the topic that the brand's own pages do not. Template actions only. Returns {data}. An id this project has no published action for is an error, whether it belongs to another project, to an action type this tool does not publish for the project, or to nothing at all. On a CONTENT_OPTIMISATION action, get_optimize_content returns the article, its suggestions and the score.

get_actions

ChatGPT
Get Peec's opportunity-scored action recommendations for improving brand visibility in AI search engines. Always call with `scope=overview` first to see which slices have the biggest opportunity, then drill down into owned, editorial, reference, or ugc with the surfaced url_classification or domain. Required parameters (read before calling) Every call must include: - project_id — the project to analyze. - scope — one of overview | owned | editorial | reference | ugc. Start with `scope=overview`. Recommended: - start_date and end_date (ISO YYYY-MM-DD). Optional — if omitted, defaults to the last 30 days (today − 30d to today). Prefer a 30-day window unless the user asks for a different one. Per-scope extras (the call will fail without them): - scope=owned → url_classification is required (e.g. "LISTICLE"). - scope=editorial → url_classification is required (e.g. "LISTICLE"). - scope=reference → domain is required (e.g. "wikipedia.org"). - scope=ugc → domain is required (e.g. "reddit.com", "youtube.com"). - scope=overview → no extras beyond the base params. Use this tool whenever the user asks for recommendations, next steps, what to do, how to improve, "what actions should I take", or any "based on this data, what should I do?" question. Never invent SEO advice. Two-step workflow Step 1 — `scope=overview`: returns opportunity rollups grouped by action_group_type × (url_classification | domain). These are navigation metadata, NOT the recommendations themselves. Use them to find which slices have the largest gap. Step 2 — drill down: for each high-opportunity slice, call again with the matching scope (owned | editorial | reference | ugc) to get the actual textual recommendations (the text column, often with markdown links to examples or targets). Mapping — how to turn an overview row into the follow-up call: - action_group_type=OWNED, url_classification=X → call scope=owned, url_classification=X. - action_group_type=EDITORIAL, url_classification=X → call scope=editorial, url_classification=X. - action_group_type=REFERENCE, domain=Y → call scope=reference, domain=Y. - action_group_type=UGC, domain=Y → call scope=ugc, domain=Y. Worked example — overview returns a row {action_group_type: "UGC", domain: "youtube.com", opportunity_score: 0.30, ...}. Follow up with scope=ugc, domain="youtube.com" and you get rows like {text: "Contact [AutoPedia](https://...). Ask them for a collaboration.", group_type: "UGC", domain: "youtube.com", opportunity_score: 3, ...}. Response shape Returns columnar JSON: {columns, rows, rowCount}. Each row is an array of values matching column order. `scope=overview` columns: - action_group_type: OWNED | EDITORIAL | REFERENCE | UGC - url_classification: populated for OWNED / EDITORIAL rows (e.g. "LISTICLE", "ARTICLE", "COMPARISON"). null for REFERENCE / UGC. - domain: populated for REFERENCE / UGC rows (e.g. "youtube.com", "wikipedia.org"). null for OWNED / EDITORIAL. - opportunity_score: continuous. Use this to sort and rank — it's the reliable ordering signal. - relative_opportunity_score: 1–3 tier (1=Low, 2=Medium, 3=High). Use this to label strength in prose. Too coarse to sort by. - gap_percentage, coverage_percentage, used_ratio, used_total: supporting stats. Exactly one of url_classification / domain is populated per overview row — that's the value to pass to the follow-up call. `scope=owned | editorial | reference | ugc` columns: - text: the recommendation string; may include markdown links. - group_type: OWNED | EDITORIAL | REFERENCE | UGC. - url_classification: e.g. "LISTICLE" (may be null). - domain: e.g. "youtube.com" (may be null). - opportunity_score: continuous — sort/rank by this. - relative_opportunity_score: 1–3 tier — label strength with this (1=Low, 2=Medium, 3=High). Presenting results After overview + drill-downs, pick the shape that fits: - Strong signal (top slice's opportunity_score is…

get_agent_readiness

ChatGPT
How ready every own brand domain and every competitor brand domain of the project are for AI agents, from Peec's agent readiness audit of each domain. Each site has a level from 0 to 5. A level is reached when every gate check of it and of every level below passes; 0 means a level 1 gate still fails. ceiling is the highest level the audit can award that site. Returns: {own: [{brand: {id, name}, domain, audit, latest_run}], competitors: [{brand: {id, name}, domain, audit}]} audit: {completed_at, level, ceiling, next_level: {level, passed_gates, total_gates, blocking_check_ids} | null, checks?: [{id, title, level, tier, outcome, why, fix, failing_pages}]} latest_run: {id, status, created_at, finished_at, error} | null - blocking_check_ids are the gate checks to fix to reach the next level; next_level is null at the ceiling. - checks is returned only with include_checks=true. tier: gate decides the level; reported (hygiene) and emerging (standards few agents use yet) never block a level. outcome is the most severe across the pages checked; absent, invalid and blocked need fixing. fix says how to make the check pass. failing_pages lists up to 5 URLs the check failed on; it is empty for a check of the whole domain, such as robots.txt. - latest_run is the own domain's newest audit run: status is queued, running, completed, failed or cancelled; error is the failure code or null; finished_at is null while it runs. Its id matches the run_id request_agent_readiness_audits returned, so call this tool again to follow a requested audit. latest_run is null when the domain was never audited. - audit is null when the domain has no audit completed in the last 90 days. own is empty when the project has no own domain. A brand with several domains appears once per domain, with the domain exactly as the brand lists it. This tool never starts an audit; request_agent_readiness_audits queues one for any domain in own. Use this for whether AI agents can read and use the site. For AI crawlers actually visiting it, use get_agent_visits.

get_agent_session

ChatGPT
Read one of the user's agent sessions in a project, a chat or a schedule run, as listed by list_agent_sessions. Returns {id, title, schedule_id, created_at, updated_at, message_count, messages}. messages holds the latest messages, oldest first, up to limit and about 40,000 characters of text, each {role, text, tool_calls?, is_text_truncated?}: the text a reader sees and the tools a message called, without reasoning or tool results. message_count is how many readable messages the session has, so a count above the messages returned means older ones were left out. schedule_id is null for a chat.

get_agent_visits

ChatGPT
Aggregate AI agent visit counts from access logs over a date range. Without group_by: returns total visit count as a single {visits: N} row. With group_by: returns one row per distinct value of the chosen dimension(s), sorted by visits descending. group_by dimensions: - bot_id: break down by bot (use list_bots to resolve names) - response_status: break down by HTTP response status (200, 404, etc.) - request_host: break down by hostname - request_path: break down by URL path Multiple group_by values produce a cross-dimensional breakdown (e.g. bot_id + response_status gives per-bot per-status counts). Use bot_ids to filter to specific bots before grouping. By default, excludes spoofed traffic and includes unverifiable traffic from bots whose operators publish no usable IP ranges. Use verification_statuses to inspect a different scope, including spoofed traffic when explicitly requested. time_bucket: bucket results by time period (hour, day, week, month). Each row will include a time_bucket timestamp marking the start of the bucket. Combine with group_by to get e.g. per-bot per-day counts. Returns: {data: [{bot_id?, response_status?, request_host?, request_path?, time_bucket?, visits}], totalCount}

get_ai_referrals

ChatGPT
People who arrived on the project's own website from an AI assistant, measured by the project's connected Google Analytics property. Without group_by: period totals as a single row. With group_by: one row per combination, up to 3 dimensions, sorted by the first requested metric descending. group_by dimensions: - assistant: ChatGPT, Perplexity, Claude, Gemini, Copilot, Grok and ~57 more. Rolls up every host an assistant uses, so prefer it over source. - platform: the company behind the assistants (OpenAI, Google, Microsoft, Anthropic...). - source: the raw referrer host (chatgpt.com). Rows grouped by source also carry assistant and platform, so you never need a second call to name a host. A referrer we do not recognise appears under its own hostname; isolate it with mediums, not assistants. - medium: GA4 session medium. Only ai-assistant and the mediums AI referrers arrive on; non-AI traffic is out of scope for this tool. - country, device: ISO country code, and desktop/mobile/tablet. - event_name: the GA4 event (page_view, purchase). - landing_page: the session's entry page, repeated on every event in that session. - page_path: the page the event fired on, UUIDs collapsed to *. Does not join to landing_page. - host: which of the project's own hostnames. metrics (default: all, minus session_starts when grouping by event_name): - events: GA4 event count. - session_starts: GA4 session_start events. NOT GA4's "sessions" metric. - conversions: GA4 key events. One visit can contribute several, and which events count is the property's own configuration. - revenue: purchase revenue in the property's reporting currency, returned as currency on the result. There is no list_event_names or list_countries tool: to discover a dimension's values, call this with group_by set to that one dimension. When building a filter, do not also filter by the dimension you are listing, or every option the user has not already picked disappears. Unknown values come back as "(not set)". Date ranges are capped at 366 days. Returns: {columns, rows, rowCount, total_count, currency}, where total_count is the number of grouped rows the filters match, not a sum of any metric.

get_brand_perception_attribute_history

ChatGPT
How one brand's prominence on each brand-perception attribute has moved over time — the series the Market view's history chart plots. Use it for trend questions (is the brand gaining or losing on an attribute, since when); for the current standing use get_brand_perception_competitive_breakdown or get_brand_perception_attribute_rankings. score is 0-100 — the brand's average prominence across that day's AI answers about the attribute, the same score as the competitive breakdown split by day; answers the brand was absent from count as 0. Display as-is, never multiply by 100. One row per attribute x day, oldest day first; every attribute carries the same days. Attributes are sorted by the brand's score on the latest day, strongest first. limit/offset paginate ATTRIBUTES, not rows, and totalCount is the total attribute count. brand defaults to the project's own brand; pass a competitor's name exactly as the competitive breakdown spells it to read theirs. The response reports the brand it read as brand. Data covers the brand-perception runs of one industry and one target market — pass industry to pick the industry; the target market is always that industry's most recently completed one and cannot be picked. The response reports the scope it used as industry and target_market, and lists the project's other industries under industries when it has more than one — say which industry the numbers describe whenever that field is present. Optionally filter to specific engine channels via model_channel_ids (see list_model_channels). Returns columnar JSON: {columns, rows, rowCount, totalCount}. Columns: attribute, date, score.

get_brand_perception_attribute_rankings

ChatGPT
How the project's own brand ranks against competitors for each brand-perception attribute. ranking is the own brand's position among every brand scored for the attribute, ordered by average prominence across all AI answers about it — lower is better, #1 means no brand is more prominent; answers the brand never surfaced in count against it, and null means it never surfaced at all. competitors lists the competing brand names AI associates with the attribute, most prominent first. Rows are sorted best-ranked first (unranked last). Data is aggregated across the brand-perception runs of one industry and one target market (no date range) — pass industry to pick the industry; the target market is always that industry's most recently completed one and cannot be picked. The response reports the scope it used as industry and target_market, and lists the project's other industries under industries when it has more than one — read a different one by passing its name back as industry, and say which industry the numbers describe whenever that field is present. Use get_brand_perception_attribute_sources with a returned name to see the sources feeding an attribute. Optionally filter to specific engine channels via model_channel_ids (see list_model_channels), or narrow by a search substring on the attribute name. Returns columnar JSON: {columns, rows, rowCount, totalCount}. rowCount is the rows in this page; totalCount is the total matching records ignoring limit/offset. Columns: name, ranking, competitors (array of brand names).

get_brand_perception_attribute_sources

ChatGPT
The sources feeding one brand-perception attribute: the URLs AI answers cited when describing the brand with this attribute. Pass the attribute name exactly as returned by get_brand_perception_brand_attributes or get_brand_perception_attribute_rankings; an unknown name returns an empty result. Data is aggregated across all brand-perception runs (no date range), and unlike the rankings and competitive-breakdown tools it is not scoped to one industry — there is no industry argument. occurrences = AI answers about the attribute citing this source (all time). retrievals = distinct chats the source was retrieved in. citation_rate = mean citations per retrieved chat — an average, NOT a percentage, can exceed 1, display as-is. Sort with order_by (default occurrences desc). Optionally filter to specific engine channels via model_channel_ids (see list_model_channels). Returns columnar JSON: {columns, rows, rowCount, totalCount}. rowCount is the rows in this page; totalCount is the total matching records ignoring limit/offset. Columns: url, title, domain, url_classification, domain_classification, occurrences, retrievals, citation_rate.

get_brand_perception_brand_attributes

ChatGPT
How AI models describe the project's own brand: attributes (e.g. "Luxury", "Racing Heritage") with a prominence score. score is 0-100 — the attribute's average prominence per AI answer; higher means the attribute is mentioned earlier and more often. Display scores as-is; they are NOT ratios, never multiply by 100. members lists the attribute's terms: the raw phrasings from AI answers grouped under it. Data is a snapshot of the latest brand-perception run (no date range). An empty result means the first run has not completed yet. Optionally filter to specific engine channels via model_channel_ids (see list_model_channels). Returns columnar JSON: {columns, rows, rowCount, totalCount}. rowCount is the rows in this page; totalCount is the total matching records ignoring limit/offset. Columns: name, score, members.

get_brand_perception_claim_sources

ChatGPT
The pages behind one fact-checked claim, each with the role it earned. Pass the claim_id returned by get_brand_perception_fact_checking_verdicts; an unknown id returns an empty result. tier is at_claim for a page cited inside the passage the claim was mined from, elsewhere for a page cited elsewhere in the same answer, and retrieved for a page the answer retrieved and never cited; a page that earned different roles in different answers keeps the strongest one. Start from the at_claim pages, since those are the likeliest to have produced the claim. Data is aggregated across every answer that made the claim and has no date range; strongest tier first. Use this rather than get_chat when the question is where a claim came from, since get_chat returns one answer's citations with no tier. Returns columnar JSON with columns, rows, rowCount, and totalCount. Columns: url, title, tier.

get_brand_perception_competitive_breakdown

ChatGPT
The full competitive breakdown matrix: for every brand-perception attribute, the average prominence of each brand (the project's own brand and its competitors) across AI answers. score is 0-100 — higher means the brand tends to be mentioned earlier when AI talks about that attribute; display as-is, never multiply by 100. is_own marks the project's own brand. One row per attribute x brand cell; attributes are sorted by the own brand's score (strongest first) and brands by score within each attribute. limit/offset paginate ATTRIBUTES, not rows — each attribute contributes one row per brand, and totalCount is the total attribute count. Data is aggregated across the brand-perception runs of one industry and one target market (no date range) — pass industry to pick the industry; the target market is always that industry's most recently completed one and cannot be picked. The response reports the scope it used as industry and target_market, and lists the project's other industries under industries when it has more than one — read a different one by passing its name back as industry, and say which industry the numbers describe whenever that field is present. Optionally filter to specific engine channels via model_channel_ids (see list_model_channels). Returns columnar JSON: {columns, rows, rowCount, totalCount}. Columns: attribute, brand, score, is_own.

get_brand_perception_fact_checking_verdicts

ChatGPT
The claims AI models make about the project's brand, each judged against one of the project's facts. One row per claim and fact: verdict is supported or contradicted (claims no fact covers are not returned), fact is the wording the claim was judged against, chats counts the distinct AI answers that made the claim, model_channel_ids lists the channels those answers came from (name the AI engine when you present them, such as ChatGPT or Perplexity, and never print the ids; channels reflect where the claim appeared historically and may include channels no longer active for the project), last_seen is the most recent day the claim appeared (ISO date). Data is aggregated across all fact-checked chats and has no date range; newest claims first. Use verdicts=["contradicted"] to find what AI gets wrong about the brand, fact_ids from list_facts to check one fact, and claim_ids to read one claim with every fact it was judged against. Two columns are opt-in, so name them in fields: prompts counts the distinct tracked prompts whose answers made the claim, and example_chat_id is the most recent answer that made it, which get_chat reads. get_brand_perception_claim_sources lists the pages behind one claim_id. Returns columnar JSON with columns, rows, rowCount, and totalCount. Default columns: claim_id, claim, fact_id, fact, verdict, chats, model_channel_ids, last_seen.

get_brand_perception_objection_sources

ChatGPT
The sources AI models retrieved when asked about one objection. Pass the objection name exactly as returned by get_brand_perception_objections; an unknown name returns an empty result. Data is aggregated across all objection runs and has no date range. citation_rate is an average, not a percentage. Returns columnar JSON with columns, rows, rowCount, and totalCount.

get_brand_perception_objections

ChatGPT
The recurring arguments AI models make against the project's brand when a buyer is deciding. score is average prominence per AI answer from 0 to 100; display it as-is. members contains the raw phrasings folded into each objection. Data is aggregated across all objection runs and has no date range. Returns columnar JSON with columns, rows, rowCount, and totalCount. Columns: name, score, members.

get_brand_report

ChatGPT
Get a report on brand visibility, sentiment, and position across AI search engines. Results are aggregated for the entire date range by default. Use the "date", "week", or "month" dimension for time-bucketed breakdowns (daily, ISO week, or calendar month). When the range spans many days, prefer "week" or "month" over "date": coarser buckets return far fewer rows (180 days ≈ 26 weeks or 6 months vs. 180 daily rows), which avoids the row limit truncating the series and keeps the trend readable. Reach for "date" only when day-level granularity is essential and the range is short. Edge buckets may be partial: a range starting or ending mid-week/mid-month produces a first/last bucket that only aggregates the in-range days, so its values can look low — don't read that as a real dip. Dimensions multiply the row count: rows = entities × dimension value combinations (e.g. 2 brands broken down by "date" over 180 days = 360 rows). The default limit of 100 will silently truncate such queries — raise "limit" to the row count you actually need. If rowCount equals limit, results were truncated; narrow the request (fewer entities, a shorter date range, fewer dimensions) or page through with "offset". Returns columnar JSON: {columns, rows, rowCount, total}. Each row is an array of values matching column order. Columns: - brand_id — the brand ID - brand_name — the brand name - visibility: 0–1 ratio — fraction of AI responses that mention this brand. 0.45 means 45% of conversations. - mention_count: number of times the brand was mentioned - share_of_voice: 0–1 ratio — brand's fraction of total mentions across all tracked brands - sentiment: 0–100 scale — how positively AI platforms describe the brand (most brands score 65–85) - position: average ranking when the brand appears (lower is better, 1 = mentioned first) - Raw aggregation fields (for custom calculations): visibility_count, visibility_total, sentiment_sum, sentiment_count, position_sum, position_count When dimensions are selected, rows also include the relevant dimension columns: prompt_id, model_id, model_channel_id, tag_id, topic_id, chat_id, date, week, month, country_code. model_channel_id, tag_id and topic_id are each followed by a model_channel_name / tag_name / topic_name column with the human-readable name. Dimensions explained: - prompt_id: individual search queries/prompts - model_id: AI search engine (e.g. chatgpt-scraper, gpt-4o, gpt-4o-search, gpt-3.5-turbo, llama-sonar, perplexity-scraper, sonar, gemini-2.5-flash, gemini-3.1-flash-lite-search, gemini-scraper, google-ai-overview-scraper, google-ai-mode-scraper, llama-3.3-70b-instruct, deepseek-r1, deepseek-v4-pro, claude-3.5-haiku, claude-haiku-4.5, claude-sonnet-4, grok-scraper, microsoft-copilot-scraper, grok-4, grok-4.3, grok-4.6, qwen-3-6-plus, qwen-3-7-plus, amazon-rufus-scraper, mistral-small-4, mistral-medium-3-5, muse-spark-1.2) — deprecated, prefer model_channel_id - model_channel_id: stable engine channel (e.g. openai-0, openai-1, qwen-0, openai-2, perplexity-0, perplexity-1, google-0, google-1, google-2, google-3, google-4, anthropic-0, anthropic-1, deepseek-0, meta-0, meta-1, xai-0, xai-1, microsoft-0, amazon-0, mistral-0, mistral-1) — survives model upgrades - tag_id: custom user-defined tags - topic_id: topic groupings - date: daily bucket (YYYY-MM-DD) - week: ISO week bucket, value is the Monday start (YYYY-MM-DD) - month: calendar month bucket, value is the first of the month (YYYY-MM-DD) - country_code: country (ISO 3166-1 alpha-2, e.g. "US", "DE") - chat_id: individual AI chat/conversation ID Two filter inputs at different SQL stages — pick by intent: - filters (WHERE, pre-aggregation): shrinks BOTH numerator and denominator of ratio metrics. Putting brand_id here narrows everything to that brand — including share_of_voice's denominator — so SoV collapses to 1.0. - having (HAVING, post-aggregation): selects which aggregated rows are returned WITHOUT shrinking ratio-metric denominators. Use brand_id here for a single-brand report where SoV stays a real [0,1] fraction (X's share against competitors per…

get_chat

ChatGPT
Get the full content of a single chat (one AI engine's response to one prompt on one date). Returns: - messages: the user prompt and assistant response(s) - brands_mentioned: brands detected in the response with their position - sources: URLs the model retrieved, with citation counts and position - links: URLs the answer wrote into its own text (e.g. a brand name hyperlinked to its homepage), with the linked text, link count and position. A link is never also a source; use get_links_report to aggregate them. - queries: search queries the model issued - products: product gallery entries extracted from the response - features: signal flags for special elements detected in the assistant response (SHOPPING, PRODUCT_COMPARISON, AD, MAP, WEB_SEARCH, LINKS). Use list_chats with the features filter to query chats by these. - maps: local-business map cards (one per business pinned in a map widget) with { name, url } where url is the Google Maps directions deeplink for that business. - ads: paid ad placements rendered by the model. Each ad has { brand_name, url, id, ad_unit_type, ads_request_id, cards } where cards carry { title, body, image_url, target_url } and target_url is the clickout URL (with attribution UTM params). - prompt: { id } - model: { id } — deprecated, prefer model_channel - model_channel: { id } — stable engine channel id (e.g. "openai-0") Use list_chats to discover chat IDs for a project.

get_chats_report

ChatGPT
Aggregate counts and rich-answer-feature shares over a project's chats for a date range. Answers questions like "how many chats", "what share rendered a map / shopping / web-search / ad / comparison result", and "how many distinct prompts / engines / countries does tag X span" — use it instead of paging through list_chats. Group by one or more dimensions, or omit dimensions for a single total row over all matching chats. Metric columns: - chat_count — chats in the group (denominator of the feature percentages) - prompt_count / model_channel_count / country_count — distinct prompts / engine channels / countries the group spans (country_count excludes chats with no country) - shopping_count / shopping_percentage — answers with a shopping / product gallery - product_comparison_count / product_comparison_percentage — answers with a product comparison - ad_count / ad_percentage — answers with an ad - map_count / map_percentage — answers with a map / local-business result - web_search_count / web_search_percentage — answers with web-search sources Percentages are 0–1 ratios of chat_count (0.75 = 75%). Coverage counts collapse to 1 for the dimension you group by, so read them against dimensions you did NOT split on. Raise "limit" for time or high-cardinality breakdowns, to the row count you need rather than to the maximum. Dimensions: prompt_id, model_id (chatgpt-scraper, gpt-4o, gpt-4o-search, gpt-3.5-turbo, llama-sonar, perplexity-scraper, sonar, gemini-2.5-flash, gemini-3.1-flash-lite-search, gemini-scraper, google-ai-overview-scraper, google-ai-mode-scraper, llama-3.3-70b-instruct, deepseek-r1, deepseek-v4-pro, claude-3.5-haiku, claude-haiku-4.5, claude-sonnet-4, grok-scraper, microsoft-copilot-scraper, grok-4, grok-4.3, grok-4.6, qwen-3-6-plus, qwen-3-7-plus, amazon-rufus-scraper, mistral-small-4, mistral-medium-3-5, muse-spark-1.2 — deprecated, prefer model_channel_id), model_channel_id (openai-0, openai-1, qwen-0, openai-2, perplexity-0, perplexity-1, google-0, google-1, google-2, google-3, google-4, anthropic-0, anthropic-1, deepseek-0, meta-0, meta-1, xai-0, xai-1, microsoft-0, amazon-0, mistral-0, mistral-1), tag_id, topic_id, date / week / month, country_code, chat_id. tag_id / topic_id / model_channel_id rows also carry a matching *_name column. Returns {columns, rows, rowCount}; each row is an array of values aligned to columns.

get_cms_drift

ChatGPT
Compare the article in a content-optimisation action against the live page in the customer's CMS, passage by passage, and report where the two disagree. The article in the action is Peec's working copy with the suggestions on it; the live page is the customer's real website. They start as the same text and come apart whenever someone edits the page in WordPress after the action was generated. That drift is what makes a publish hit a conflict, because a suggestion written against wording the page no longer holds cannot be placed. Reach for it before publishing, so you can warn the user what has moved; after a publish came back with conflicts, to explain which passages they are; and whenever the user asks whether their page still matches what Peec is proposing. Use get_cms_page when you just want the page's text, and get_optimize_content for the article and its suggestions. Returned fields: - changed — passages the page still holds in wording the action never saw. Each has block_index, expected (the wording the action has) and current (what the page says there now). suggestion_id and suggestion_state (pending, accepted or rejected) are present when a suggestion sits on that passage, which is the case that will conflict on publish. - missing — passages that could not be located safely; a missing or ambiguous match does not prove deletion. - content_hash — the page state this read was taken against. Pass it back to publish_cms_content when the user decides to overwrite a conflict. - content_version — the working article version. Pass it with content_hash to sync_cms_content when reconciling reviewed changes. - edit_url — where the user opens the page in their CMS. - message — a plain sentence covering the state, including when there is nothing to compare. Both lists empty means no differences were detected in comparable passages. It does not guarantee a conflict-free publish. An empty answer with comparable false means there was nothing to compare: no CMS connected, no entry for this page, or no optimized content yet. Returns {data}. Read-only: nothing on the customer's site changes.

get_cms_page

ChatGPT
Read the page as the customer's own website serves it today: the live wording in their CMS, not Peec's copy of it. There are two documents behind a content-optimisation action and they are not the same thing. The article in the action is Peec's working copy, carrying the suggestions and whatever the user has accepted so far — read that with get_optimize_content. The live page is what visitors and AI crawlers actually see, and an editor can change it in WordPress at any time without Peec knowing. This tool reads the live page. Reach for it when the user asks what their page currently says, when they are about to publish and you want to describe what is about to change, or when a publish came back with a conflict and you need the page's real wording to explain it. For a passage-by-passage comparison use get_cms_drift instead — this tool just hands you the page. Pass the id of a CONTENT_OPTIMISATION action from list_actions. The tool resolves its saved CMS import or publishing destination, including when the action's page_url points to an uploaded file rather than the live page. Returned fields: - publish_state, draft_edit_url, draft_content_hash, publish_message — draft review readiness. Show the draft link and wait for explicit approval before live publishing. The hash alone is not user approval. - connected — whether the project has a CMS connected at all. False means there is nothing to read and nothing to publish to; say so instead of guessing. - page_found — whether that site serves the page this action is about. A connected site that does not serve it cannot be published to either. - title — the entry's title field, which is separate from its body. - text — the page's visible text, one block per line, with the CMS's own markup stripped. Quote from this when you tell the user what the page says. - page_url, edit_url — where the page is published, and where the user opens it in their CMS. - status — publish, draft and so on, as the CMS reports it. - not_rewritten — kinds of block the page holds that Peec never touches, such as embeds, shortcodes and raw HTML. Their text is absent from text. - message — a plain sentence covering the state, including why nothing could be read. Returns {data}. Read-only: nothing on the customer's site changes.

get_domain_report

ChatGPT
Get a report on source domain visibility and citations across AI search engines. Results are aggregated for the entire date range by default. Use the "date", "week", or "month" dimension for time-bucketed breakdowns (daily, ISO week, or calendar month). When the range spans many days, prefer "week" or "month" over "date": coarser buckets return far fewer rows (180 days ≈ 26 weeks or 6 months vs. 180 daily rows), which avoids the row limit truncating the series and keeps the trend readable. Reach for "date" only when day-level granularity is essential and the range is short. Edge buckets may be partial: a range starting or ending mid-week/mid-month produces a first/last bucket that only aggregates the in-range days, so its values can look low — don't read that as a real dip. Dimensions multiply the row count: rows = domains × dimension value combinations (e.g. 5 domains broken down by "date" over 180 days = 900 rows). The default limit of 100 will silently truncate such queries — raise "limit" to the row count you actually need. If rowCount equals limit, results were truncated; narrow the request (fewer entities, a shorter date range, fewer dimensions) or page through with "offset". Returns columnar JSON: {columns, rows, rowCount}. Each row is an array of values matching column order. Columns: - domain: the source domain (e.g. "example.com") - classification: domain type — Corporate (official company sites), Editorial (news, blogs, magazines), Institutional (government, education, nonprofit), UGC (social media, forums, communities), Reference (encyclopedias, documentation), Competitor (direct competitors), You (the user's own domains), Other, or null - retrieved_percentage: 0–1 ratio — fraction of chats that included at least one URL from this domain. 0.30 means 30% of chats. - retrieval_rate: average number of URLs from this domain pulled per chat. Can exceed 1.0 — values above 1.0 mean multiple pages from the same domain are retrieved per conversation. - citation_rate: average number of inline citations when this domain is retrieved. Can exceed 1.0 — higher values indicate stronger content authority. - retrieved_chat_count: the canonical "retrievals" metric — number of distinct chats in which at least one URL from this domain was retrieved. When a user asks about "retrievals" for a domain, report THIS number; it matches the Domains table in the UI. - retrieval_count: URL-level count — total number of distinct URL retrievals from this domain across all chats (raw numerator of retrieval_rate). A single chat can retrieve several URLs, so this is always at least as large as retrieved_chat_count and is NOT the canonical "retrievals" number. - citation_count: total number of citations from this domain (raw count). - mentioned_brand_ids: array of brand IDs mentioned alongside URLs from this domain (may be empty) When dimensions are selected, rows also include the relevant dimension columns: prompt_id, model_id, model_channel_id, tag_id, topic_id, chat_id, date, week, month, country_code. model_channel_id, tag_id and topic_id are each followed by a model_channel_name / tag_name / topic_name column with the human-readable name. Dimensions explained: - prompt_id: individual search queries/prompts - model_id: AI search engine (e.g. chatgpt-scraper, gpt-4o, gpt-4o-search, gpt-3.5-turbo, llama-sonar, perplexity-scraper, sonar, gemini-2.5-flash, gemini-3.1-flash-lite-search, gemini-scraper, google-ai-overview-scraper, google-ai-mode-scraper, llama-3.3-70b-instruct, deepseek-r1, deepseek-v4-pro, claude-3.5-haiku, claude-haiku-4.5, claude-sonnet-4, grok-scraper, microsoft-copilot-scraper, grok-4, grok-4.3, grok-4.6, qwen-3-6-plus, qwen-3-7-plus, amazon-rufus-scraper, mistral-small-4, mistral-medium-3-5, muse-spark-1.2) — deprecated, prefer model_channel_id - model_channel_id: stable engine channel (e.g. openai-0, openai-1, qwen-0, openai-2, perplexity-0, perplexity-1, google-0, google-1, google-2, google-3, google-4, anthropic-0, anthropic-1, deepseek-0, meta-0, meta-1, xai-0, xai-1, microsoft-0, amazon-0, mistral-0, mistral-1) — survi…

get_optimize_content

ChatGPT
Read the article behind a content-optimisation action, as the user sees it on the Optimize content screen: the current text, the suggestions listed beside it and the optimisation score. Pass the id of a CONTENT_OPTIMISATION action from list_actions. Call this whenever the user asks about the article behind one, a suggestion on it, or where to edit it. Never ask them to paste the article. Returned fields: - article — the whole article as plain text, with the suggestions resolved the way the screen shows them: an accepted rewrite reads as its new wording, a pending or dismissed one as the original. Quote from this rather than guessing at the page. - suggestions — one entry per suggestion, each with category, text, state (pending, accepted or rejected) and kind. A rewrite carries wording to accept or dismiss; an edit only names what is missing, so acting on it means writing the text. - page_url — the page being optimised. - score — the optimisation score out of 100, reflecting the suggestions accepted so far. Returns {data}. An action that is not a content optimisation, is deleted, or belongs to another project, is an error.

get_product

ChatGPT
Get one product's detailed metrics over a date range — the drill-down companion to list_products, which returns a thin row per product. Returns {data, primary_currency}, where data is null if the product is not in the project. data always includes: - id, name, brand, source (CATALOG or LLM), first_seen_at - visibility (0–1), win_rate (0–1), avg_position (rank, lower is better), avg_rating (mean 0–5 star rating across the product's AI mentions; null when none carried a rating), mention_count - *_delta for each metric above (visibility_delta, win_rate_delta, avg_position_delta, avg_rating_delta, mention_count_delta) — change vs the immediately preceding equal-length period; null when the previous period had nothing to compare against Everything else is opt-in via the 'fields' argument (default: none) to keep the response lean — list any of these to include them: - description, image_url - price_range / price_override — per-currency effective catalog range (min/max) and the raw overrides behind it - ai_price_map / ai_price_delta_map — per-currency median price across the product's AI mentions, and its change - variants — the product's live catalog variants (SKU-level), each with id, name, and a per-currency price_map (ISO-4217 → price; a variant carries a single entry). Capped at 50 with no pagination: a product with more than 50 variants returns only the first 50 by name. - four QFO (query fan-out) breakdowns of what surfaced this product, each up to 25 rows with distinct_chat_count (+ its previous-period value and delta): shopping_queries / shopping_query_terms (Google-Shopping fan-out queries and their n-grams) and fanout_queries / fanout_query_terms (web-search fan-out queries and their n-grams). Unrequested QFO breakdowns are skipped, not just omitted — no ClickHouse pass runs for them. Visibility divides by the product's relevant-prompt chats (prompts it is mentioned in or SODA-linked to), not all shopping chats. Metrics cover [start_date, end_date]; deltas compare against the equal-length period ending the day before start_date. With merchant_ids, the headline metrics, price maps, and QFO breakdowns count only chats where the product is sold through one of those merchants (the visibility denominator stays unscoped) — pass one merchant id for that seller's rating, price, mentions, and the queries that surface its offers.

get_project_profile

ChatGPT
Read a project's brand profile — the description, industry, brand-identity adjectives, target markets, audience distribution, and product/service list that Peec uses to generate prompt suggestions. Returns { profile } where profile may be null if the project hasn't been profiled yet. Call this before set_project_profile so you can show the user the current values.

get_prompt_suggestion_generation

ChatGPT
Read the authoritative status of a run returned by generate_prompt_suggestions. The call waits for the run to finish rather than answering at once, so one call replaces a polling loop. QUEUED and RUNNING are non-terminal; SUCCEEDED and FAILED are terminal. A non-terminal answer means the run outlasted the wait, not that it failed: call again to keep waiting. A successful run can produce zero suggestions. After success, call list_prompt_suggestions to review the current suggestions.

get_shopping_attributes

ChatGPT
Compare the qualitative characteristics and features that AI engines associate with a product (or the whole catalog) against competitors. These attributes are extracted from shopping answers and are qualitative — for the numeric shopping metrics (visibility, win rate, position) use get_shopping_summary or get_shopping_trend instead. scope=product compares one product (needs product_id); scope=overview compares the whole catalog. compare_by picks the grid columns: brand (default) or product (scope=product only). tab picks the value type. Returns a nested grid (not columnar): { tab, competitors[], groups[], total_groups }. Each competitor is a brand ({global_brand_id, name, domain, mentions}) or product ({product_id, name, brand_name, image_url, mentions}); every group's per-competitor arrays align to the competitors order. Group shape by tab: - characteristics: { dimension_id, name, total_mentions(+_delta), value_count, values: [{value, mentions(+_delta), competitor_mentions[]}] } - facts: { ..., value_type: BOOLEAN, unit, own: {true_count, false_count, unrecognized_count}, competitor_values[] } - dimensions: { ..., own: {min, max, average, median} | null, competitor_values: (stats | null)[] } Deltas are vs an explicit comparison window (previous_start_date/previous_end_date) or the equal-length window immediately before.

get_shopping_summary

ChatGPT
Return catalog-wide shopping metrics over a date range — avg_visibility, avg_win_rate, and avg_position, each with a period-over-period delta — as a single aggregated row across the filtered scope. Deltas compare against previous_start_date/previous_end_date when given, else the auto-derived previous period. For a per-entity or per-time breakdown, use get_shopping_trend or list_shopping_performance.

get_shopping_trend

ChatGPT
Return a per-bucket shopping time series (visibility, win_rate, avg_position, sov) for specific products or global brands over a date range. Requires bucket (day/week/month) and exactly one of product_ids or brand_ids. Returns { entity_type, series[] }, one series per entity with a points array; has_data flags buckets with no underlying chats. For a single catalog-wide aggregate use get_shopping_summary; for a ranked table use list_shopping_performance.

get_url_content

ChatGPT
Fetches and returns the content of a URL for downstream analysis — the markdown Peec extracted from the page. Returns the exact content Peec's pipeline indexed, with no extra fetch. Works for any URL Peec has scraped for the project; you do not need to call get_url_report first. If Peec has no record of the URL it returns 404. Input notes: - url is the full URL, copied verbatim. Trailing slashes and scheme variations change the resolved source ID. - max_length caps the returned content (default 100000 characters). If the stored content is longer, truncated=true — re-request with a higher max_length. Returned fields: - url, title, domain, channel_title: page metadata - classification: domain-level classification - url_classification: page-level classification (HOMEPAGE, LISTICLE, COMPARISON, ...) - content: the page's markdown content. null when the URL is tracked but scraping hasn't completed yet (can take up to 24h). - content_length: original character length before truncation (0 when content is null) - truncated: true if content was truncated to max_length - content_updated_at: ISO timestamp of last scrape, or null if not yet scraped

get_url_report

ChatGPT
Get a report on source URL visibility and citations across AI search engines. Results are aggregated for the entire date range by default. Use the "date", "week", or "month" dimension for time-bucketed breakdowns (daily, ISO week, or calendar month). When the range spans many days, prefer "week" or "month" over "date": coarser buckets return far fewer rows (180 days ≈ 26 weeks or 6 months vs. 180 daily rows), which avoids the row limit truncating the series and keeps the trend readable. Reach for "date" only when day-level granularity is essential and the range is short. Edge buckets may be partial: a range starting or ending mid-week/mid-month produces a first/last bucket that only aggregates the in-range days, so its values can look low — don't read that as a real dip. Dimensions multiply the row count: rows = URLs × dimension value combinations (e.g. 5 URLs broken down by "date" over 180 days = 900 rows). The default limit of 100 will silently truncate such queries — raise "limit" to the row count you actually need. If rowCount equals limit, results were truncated; narrow the request (fewer entities, a shorter date range, fewer dimensions) or page through with "offset". Returns columnar JSON: {columns, rows, rowCount}. Each row is an array of values matching column order. Columns: - url: the full source URL (e.g. "https://example.com/page") - classification: page type — Homepage, Category Page, Product Page, Listicle (list-structured articles), Comparison (product/service comparisons), Profile (directory entries like G2 or Yelp), Alternative (alternatives-to articles), Discussion (forums, comment threads), How-To Guide, Article (general editorial content), Other, or null - title: page title or null - channel_title: channel or author name (e.g. YouTube channel, subreddit) or null - citation_count: total number of explicit citations across all chats - retrieval_count: total number of distinct chats that retrieved this URL, regardless of whether it was cited - citation_rate: average number of inline citations per chat when this URL is retrieved. Can exceed 1.0 — higher values indicate more authoritative content. - mentioned_brand_ids: array of brand IDs mentioned alongside this URL (may be empty) When dimensions are selected, rows also include the relevant dimension columns: prompt_id, model_id, model_channel_id, tag_id, topic_id, chat_id, date, week, month, country_code. model_channel_id, tag_id and topic_id are each followed by a model_channel_name / tag_name / topic_name column with the human-readable name. Dimensions explained: - prompt_id: individual search queries/prompts - model_id: AI search engine (e.g. chatgpt-scraper, gpt-4o, gpt-4o-search, gpt-3.5-turbo, llama-sonar, perplexity-scraper, sonar, gemini-2.5-flash, gemini-3.1-flash-lite-search, gemini-scraper, google-ai-overview-scraper, google-ai-mode-scraper, llama-3.3-70b-instruct, deepseek-r1, deepseek-v4-pro, claude-3.5-haiku, claude-haiku-4.5, claude-sonnet-4, grok-scraper, microsoft-copilot-scraper, grok-4, grok-4.3, grok-4.6, qwen-3-6-plus, qwen-3-7-plus, amazon-rufus-scraper, mistral-small-4, mistral-medium-3-5, muse-spark-1.2) — deprecated, prefer model_channel_id - model_channel_id: stable engine channel (e.g. openai-0, openai-1, qwen-0, openai-2, perplexity-0, perplexity-1, google-0, google-1, google-2, google-3, google-4, anthropic-0, anthropic-1, deepseek-0, meta-0, meta-1, xai-0, xai-1, microsoft-0, amazon-0, mistral-0, mistral-1) — survives model upgrades - tag_id: custom user-defined tags - topic_id: topic groupings - date: daily bucket (YYYY-MM-DD) - week: ISO week bucket, value is the Monday start (YYYY-MM-DD) - month: calendar month bucket, value is the first of the month (YYYY-MM-DD) - country_code: country (ISO 3166-1 alpha-2, e.g. "US", "DE") - chat_id: individual AI chat/conversation ID Two filter inputs at different SQL stages — pick by intent: - filters (WHERE, pre-aggregation): population fields shrink the chat scope; source-side and per-row mentioned-brand predicates (mentioned_brand_id, mentioned_brand_count, gap) shrink the source-ro…

import_url_tags

ChatGPT
Tag a list of up to 5000 URLs in one call, such as a campaign's pages from a spreadsheet, and optionally set each URL's classification. Every row is checked first: if any is invalid, nothing is applied and the response lists every error with its row, the 1-based position in rows. Otherwise, all at once, it creates the source tags the project does not have yet (names match case-insensitively), adds each row's tags to its URL without removing any, and sets the classification where a row gives one. Use this over create_source_tags and update_source_tag_assignments when tagging more than a few URLs or when the tags are named rather than known by id. Returns {applied, urlCount, assignmentsAdded, assignmentsAlreadyPresent, classificationsSet, tags: [{id, name, urlCount, created}]} with tags ordered by URL count, or {applied: false, errors: [{row, message}]}.

invite_project_members

ChatGPT
Invite up to 50 people to the project by email in one call. Each one gets the same invitation email as an invite from the app's members page. role is VIEWER (sees the project's data, the default) or OWNER (can also change the project and manage its members). Only use OWNER when the user asked for it. Returns: - invited: email, role and access - "granted" when the email already has a Peec account and can open the project now, "pending" until the person signs up from the email. - skipped: reason "already_member", "already_invited" or "duplicate" (the same email earlier in the call). - rejected: a message saying why that person could not be invited. Fails as a whole when the company has turned off email invitations. No tool lists members or invitations, so this result is the only verification.

list_action_platforms

ChatGPT
The third-party sites a project has actions on, alphabetically — the values list_actions accepts in its platforms filter. A platform is whichever domain an AI engine cited for this brand, so unlike the other filter dimensions it is per project and open-ended, and no enum of it appears in any schema. Own-site actions carry no platform and never appear here. Returns columnar JSON: {columns, rows, rowCount, totalCount}. Columns: platform.

list_actions

ChatGPT
List a project's actions — the same set the Actions page shows. Each action names a page or a site and a concrete change to make to it, with the impact expected if it is done. The list holds both the actions Peec generated and the ones the customer wrote themselves; created_by says which, and only a customer one can be deleted or reshaped. priority, assignee_user_id, due_on and tag_ids are how the page is used as a task tracker — they are opt-in columns, so name them in fields to read them. This is the current Actions model. get_actions is a different, older opportunity-rollup tool; fall back to it only when this tool returns no actions. These kinds of action are published. TEMPLATE_ACTION is a per-platform playbook filled in for one page — pitch an editor, get listed, grow reviews, join a conversation. CONTENT_BRIEF is net-new content to write, with an outline. CATEGORY_SITUATION_BRIEF is also net-new content, ready-to-use briefs carried in its steps rather than an outline. CONTRADICTIONS_EXTERNAL_SOURCES requests correction of one third-party source page that conflicts with a verified brand fact. CONTRADICTIONS_OWNED_SOURCES corrects one source page on a domain the brand owns. SEO_ISSUE is a technical fix to a site the brand controls, and applies to the whole site rather than one page: domain is the site, category the audit check behind it, and source names the audit rather than a page. An SEO_ISSUE in the crawlability category means Peec's own audit crawler could not read the site, which pauses Peec's page-level recommendations for it; it says nothing about whether AI engines can reach the site, so never present it as a cause of changes in retrieval or citation. ROBOTS_TXT says a site's robots.txt blocks AI crawlers. CONTENT_OPTIMISATION improves an existing page the brand owns, and appears only on projects with content optimisation enabled; get_optimize_content returns its article, suggestions and score. Use get_action with a returned id for the steps to work through, the brief, the competitor demand behind it and the prompts an action affects. Filters combine with AND. The four surface filters — targets, groups, archetypes, platforms — are the exception: they combine with OR across the four, so passing an owned target alongside a platform widens the answer instead of narrowing it. impact is how much the action is expected to gain, banded against every action in the project, so it reads the same whatever filters are applied — on an SEO_ISSUE it bands the issue's severity instead. It is the only measure of expected gain this tool returns; there is no finer-grained figure to report or infer. Returns columnar JSON: {columns, rows, rowCount, totalCount}. rowCount is the rows in this page; totalCount is every action matching the filters, ignoring limit and offset.

list_agent_sessions

ChatGPT
List the user's agent sessions in a project, most recently active first: their chats and the runs of their agent schedules. Pass schedule_id for one schedule's runs, then read a session with get_agent_session. Returns columnar JSON: {columns, rows, rowCount, totalCount}. Columns: id, title, turn_count, last_turn_state, created_at, updated_at, schedule_id, run_trigger, run_status, run_reason, scheduled_for. last_turn_state: running, complete, error, aborted, refused, awaiting_approval, awaiting_choice. The run columns are null for a chat; run_status: queued, running, awaiting_input, success, error, skipped; run_reason says why a run failed or was skipped; scheduled_for is null for a run started by hand.

list_bots

ChatGPT
List all known AI crawler/agent bots that visit the site (e.g. GPTBot, ClaudeBot, PerplexityBot). Each bot has an ID, provider, and type. Bot types: - training: crawlers that collect data for model training (e.g. GPTBot, ClaudeBot) - search: bots that retrieve content for AI-powered search (e.g. PerplexityBot) - userQuery: bots triggered by real-time user queries - other: miscellaneous bots Use the returned bot IDs with get_agent_visits to filter visit counts by specific bots. Returns: {data: [{id, provider, type}]}

list_brand_perception_attribute_clusters

ChatGPT
The editable taxonomy behind the brand-perception Market view: every attribute with its cluster_id, its name and the terms grouped under it. An attribute is a grouping the Market view scores (e.g. "Luxury"); a term is a raw phrasing extracted from AI answers (e.g. "hand-built") that Peec has grouped under an attribute. Use those two words with the user; the cluster_id is an internal handle. Use this tool to resolve the cluster_id values edit_brand_perception_attribute_clusters needs, and to see terms that are grouped wrongly. Prefer get_brand_perception_brand_attributes when the question is about scores — this tool carries no scores, but it does list attributes that have no score yet, including ones just added. unassigned holds terms that belong to no attribute (not paginated). is_custom marks an attribute a person added by hand through Add attribute. Returns columnar JSON: {columns, rows, rowCount, totalCount, unassigned}. Columns: cluster_id, name, is_custom, members (the attribute's terms).

list_brand_social_channels

ChatGPT
List the social channels configured for a project's own brand and competitors. Optionally filter by brand ID. Returns columnar JSON with id, brand_id, platform, channel_id, and channel_handle.

list_brands

ChatGPT
List brands tracked in a project — includes the user's own brand and competitors. Use this tool to resolve brand names to IDs before filtering reports (brand_id filter), and to label brand IDs from report output with their human-readable names before presenting results. Returns columnar JSON: {columns, rows, rowCount, totalCount}. rowCount is the rows in this page; totalCount is the total matching records ignoring limit/offset. Columns: id, name, domains, aliases, is_own, regex, color, source. aliases are alternate names the brand is matched under. A nonempty regex overrides name and alias matching; null means none is configured. is_own indicates which brand belongs to the user. color is the stored hex color; null means none is set and the app shows an automatic one. source is how the brand was added: 'onboarding' for competitors Peec seeded at project start, 'suggestion' for a brand suggestion someone accepted, 'manual' for a brand created directly through the app, API or this server, so a 'manual' brand may have been created by an agent. null means the brand predates source tracking. These are the brands a project tracks for visibility reporting — separate from list_global_brands, which searches the global product catalog used when creating products.

list_categories

ChatGPT
List a project's product categories. Categories are an org-wide tree (e.g. Footwear > Shoes > Running Shoes); each row carries its full path and its parent_id, so the flat list rebuilds the tree. Use a row's id in the category_ids of create_products or update_products to categorize products. Returns columnar JSON: {columns, rows, rowCount, totalCount}. Columns: id, name, path, parent_id.

list_chats

ChatGPT
List chats (individual AI responses) for a project over a date range. Each chat is produced by running one prompt against one AI engine on a given date. Filters: - brand_id: only chats that mentioned the given brand - prompt_id: only chats produced by the given prompt - model_id: only chats from the given AI engine (chatgpt-scraper, gpt-4o, gpt-4o-search, gpt-3.5-turbo, llama-sonar, perplexity-scraper, sonar, gemini-2.5-flash, gemini-3.1-flash-lite-search, gemini-scraper, google-ai-overview-scraper, google-ai-mode-scraper, llama-3.3-70b-instruct, deepseek-r1, deepseek-v4-pro, claude-3.5-haiku, claude-haiku-4.5, claude-sonnet-4, grok-scraper, microsoft-copilot-scraper, grok-4, grok-4.3, grok-4.6, qwen-3-6-plus, qwen-3-7-plus, amazon-rufus-scraper, mistral-small-4, mistral-medium-3-5, muse-spark-1.2) — deprecated, prefer model_channel_id - model_channel_id: only chats from the given engine channel (openai-0, openai-1, qwen-0, openai-2, perplexity-0, perplexity-1, google-0, google-1, google-2, google-3, google-4, anthropic-0, anthropic-1, deepseek-0, meta-0, meta-1, xai-0, xai-1, microsoft-0, amazon-0, mistral-0, mistral-1) - features: only chats that contain all of the given features (SHOPPING, PRODUCT_COMPARISON, AD, MAP, WEB_SEARCH) If both model_id and model_channel_id are provided, model_channel_id takes precedence and model_id is ignored. Excludes chats whose prompt has been deleted or archived. Set include_archived_prompts=true to include chats for archived prompts (e.g. historical lookback for a prompt that is no longer tracked). Chats for deleted prompts are always excluded. Use the returned chat IDs with get_chat to retrieve full message content, sources, and brand mentions. Returns columnar JSON: {columns, rows, rowCount, totalCount}. rowCount is the rows in this page; totalCount is the total matching records ignoring limit/offset. Columns: id, prompt_id, model_id, model_channel_id, date, features.

list_domain_classifications

ChatGPT
List the custom domain classifications defined for a project. These complement the built-in classifications (Corporate, Competitor, Editorial, Institutional, Other, Reference, UGC, You, Related) and can be assigned to domains via assign_domain_classification. Returns columnar JSON: {columns, rows, rowCount, totalCount}. Columns: name, color.

list_facts

ChatGPT
List the facts a project uses to check claims found in AI answers. Manual facts were added by a person; website facts were extracted from the project's site. An inactive fact remains visible here but is excluded from future fact-checking. Soft-deleted facts are never returned. Use this tool to resolve fact IDs before update_facts or delete_facts. Returns columnar JSON: {columns, rows, rowCount, totalCount, fact_limit, active_fact_count}. fact_limit is how many active facts the project's plan allows (null means unlimited) and active_fact_count how many it holds now, so fact_limit minus active_fact_count is the room left before create_facts is rejected. Columns: id, text, origin, is_active, edited_at, created_at. Results are newest first.

list_global_brands

ChatGPT
Search Peec's global brand catalog — the shared registry of real-world brands (e.g. Nike, Apple) that products attach to. Use it to find the global_brand_id for a brand before creating products with create_products. This is NOT the same as list_brands: list_brands returns the brands you track inside a project (your own brand plus the competitors you monitor for AI visibility), whereas list_global_brands searches every brand in Peec's catalog. The two have different ids and are not interchangeable. Primarily used with search to look up a brand by name (matches names and aliases). Pass ownership ('own', 'competitor', or 'all') instead to list the project's shopping brands by global_brand_id — the ids shopping product filters take — ranked by mentions, with their mention_count and is_own. Returns columnar JSON: {columns, rows, rowCount, totalCount}. rowCount is the rows in this page; totalCount is the total matches ignoring limit/offset. Columns: id, name, domain, description, mention_count, is_own.

list_merchants

ChatGPT
List the merchants (sellers, e.g. Amazon / eBay) whose product offers surfaced in AI answers, ranked over a date range. Each row carries mention_count, share_of_voice (0–1: this merchant's mentions over all merchants' mentions in the filtered population), win_rate (0–1 buy-box rate: position-1 mentions over all mentions), avg_position (rank, lower is better), avg_rating (mean 0–5 star rating; null when unrated), and a *_delta for each vs the previous window. Scope the population with category_ids or product_ids for per-category or per-product seller breakdowns — with product_ids, share_of_voice is the share among that product's sellers. merchant_ids instead keeps only those merchants' rows without shrinking the share_of_voice denominator (e.g. to compare two known sellers). Pass a merchant_id from here to get_product's merchant_ids for that seller's per-product rating and price. Merchants with no current-window mentions are omitted.

list_model_channels

ChatGPT
List the AI engine channels tracked by Peec. A model channel is a stable identifier for an AI engine (e.g. "openai-0" = ChatGPT UI) that persists even as the underlying model is upgraded — use it to filter or break down reports by engine without worrying about model version changes. Use this tool to resolve channel descriptions (e.g. "ChatGPT UI", "Perplexity") to channel IDs before filtering reports (model_channel_id filter), and to label channel IDs from report output before presenting results. The current_model_id column gives the model ID currently active in the channel — pass this as model_id where reports require it. is_active indicates whether the channel is enabled for this project — inactive channels return empty data. unsupported_country_codes lists country codes that cannot be used with this channel (chats requested for those countries are not created). Returns columnar JSON: {columns, rows, rowCount}. Columns: id, description, current_model_id, is_active, unsupported_country_codes.

list_models

ChatGPT
Deprecated — prefer list_model_channels, which returns stable channel IDs that survive model upgrades. List AI engines (models) tracked by Peec. Use this tool to resolve model names (e.g., "ChatGPT", "Perplexity", "Gemini") to IDs before filtering reports (model_id filter/dimension), and to label model IDs from report output with their human-readable names before presenting results. Match user-supplied names against the name column; the id column is the canonical string to pass back as model_id. is_active indicates whether the model is enabled for this project — inactive models will return empty data in reports. Returns columnar JSON: {columns, rows, rowCount}. Columns: id, name, is_active.

list_products

ChatGPT
List a project's products with headline metrics over a date range, filtered by the shopping filter pack. Returns columnar JSON: {columns, rows, rowCount, totalCount}. rowCount is the rows in this page; totalCount is the total matching records ignoring limit/offset. Columns: id, name, brand, source (CATALOG = claimed/uploaded, LLM = AI-detected), image_url, price_range (per-currency effective range), categories (category ids), mention_count, win_count, avg_position, avg_rating (mean 0–5 star rating across the product's AI mentions; null when none carried a rating), visibility, share_of_voice. Metrics cover [start_date, end_date]. For catalog cleanup, dedup, or category/name fixes, filter to source=CATALOG — LLM products aren't part of the user's catalog.

list_projects

ChatGPT
List active projects the authenticated user has access to. By default, only projects with an active status (CUSTOMER, PITCH, TRIAL, ONBOARDING, API_PARTNER) are returned — this is what you want in almost every case. Only set include_inactive to true if the user asked for a specific project that wasn't in the active list; do not set it preemptively. Returns columnar JSON: {columns, rows, rowCount}. Columns: id, name, status, language_code (ISO 639-1, the language the project's prompts run in). The id is used as project_id in other tools. Call this first to discover available projects.

list_prompt_suggestions

ChatGPT
List a project's prompt suggestions — prompts generated by Prompt discovery and awaiting review, which are not tracked and produce no data until accepted. Accept or reject them with finalize_prompt_suggestions. Their ids are prefixed pr_, and a suggestion keeps that id when accepted, so the accepted prompt is findable under the same id with list_prompts. Filter by topic_id to review one topic at a time. Returns columnar JSON: {columns, rows, rowCount}. Columns: id, text, topic_id, tag_ids (array of tag ID strings — resolve names with list_tags), country (the market the suggestion was generated for), volume (relative search volume, or null when unavailable). Pass fields to return only the columns you need.

list_prompts

ChatGPT
List prompts (conversational questions tracked daily across AI engines) in a project. Supports filtering by topic_id, tag_id, country_code, and is_archived. Returns only active prompts by default — pass is_archived=true to list archived prompts instead (e.g. when a prompt_id from older report output isn't found among the active ones). Use the search parameter to resolve prompt text to IDs (fuzzy, ranked by relevance) before filtering reports (prompt_id filter/dimension), and use this tool to label prompt IDs from report output with their actual text before presenting results. Search scans at most the 20000 most recent prompts and sets search_truncated: true in the result when the project exceeds that. Returns columnar JSON: {columns, rows, rowCount, totalCount}. rowCount is the rows in this page; totalCount is the total matching records ignoring limit/offset. State a count, a total, or a per-topic or per-tag breakdown only from totalCount, from one call filtered to each group, or after paging to the end — the rows of a single call never establish a total, and limit is capped at 1000. A totalCount returned alongside search_truncated: true counts only the scanned prompts and undercounts the project. Columns: id, text, tag_ids (array of tag ID strings), tags (array of tag names, aligned with tag_ids), topic_id (string or null), topic (topic name, string or null), country_code (ISO 3166-1 alpha-2 country the prompt is tracked from, e.g. "US"; a prompt carrying none of its own reports the project default), volume (relative search volume bucket: "very low" | "low" | "medium" | "high" | "very high", or null when unavailable — describe volume to users using the bucket label), is_archived (boolean — true when the prompt is no longer tracked daily), is_fact_checking_enabled (boolean — true when the prompt is selected for fact-checking), created_at (ISO 8601 date string, e.g. "2025-09-22", when the prompt was created — use to identify prompts older than a given age). When presenting prompts to users, use the name columns (text, topic, tags) — the id columns exist only for filtering. Pass fields to return only the columns you need.

list_referral_sources

ChatGPT
Every AI assistant Peec can attribute referral traffic to, whether or not a project has seen traffic from it. Use it to resolve the exact display name for the assistants filter on get_ai_referrals, which rejects a name it does not recognise, and to recognise a raw host in that tool's results. One row per referrer host, so an assistant reachable on several hosts (chatgpt.com and chat.openai.com) appears once per host. The list is maintained by hand and reviewed quarterly, so a very new assistant may be missing. For the assistants that actually sent a project traffic, call get_ai_referrals with group_by=["assistant"] instead — this tool takes no project and no date range. Returns: {columns, rows, rowCount, total_count}.

list_search_queries

ChatGPT
List the general web-search queries an AI engine fanned out to while answering prompts in a project over a date range — the text sub-queries it sent to a search index, NOT product/shopping lookups (use list_shopping_queries for those). Each row represents one web-search sub-query the engine issued for a given chat. Filters: - prompt_id: only queries from chats produced by this prompt - chat_id: only queries from this chat - model_id: only queries from this AI engine (chatgpt-scraper, gpt-4o, gpt-4o-search, gpt-3.5-turbo, llama-sonar, perplexity-scraper, sonar, gemini-2.5-flash, gemini-3.1-flash-lite-search, gemini-scraper, google-ai-overview-scraper, google-ai-mode-scraper, llama-3.3-70b-instruct, deepseek-r1, deepseek-v4-pro, claude-3.5-haiku, claude-haiku-4.5, claude-sonnet-4, grok-scraper, microsoft-copilot-scraper, grok-4, grok-4.3, grok-4.6, qwen-3-6-plus, qwen-3-7-plus, amazon-rufus-scraper, mistral-small-4, mistral-medium-3-5, muse-spark-1.2) - model_channel_id: only queries from this channel (openai-0, openai-1, qwen-0, openai-2, perplexity-0, perplexity-1, google-0, google-1, google-2, google-3, google-4, anthropic-0, anthropic-1, deepseek-0, meta-0, meta-1, xai-0, xai-1, microsoft-0, amazon-0, mistral-0, mistral-1) - topic_id: only queries from chats whose prompt belongs to this topic - tag_id: only queries from chats whose prompt carries this tag Use get_chat with a returned chat_id to inspect the full AI response that produced these sub-queries. Returns columnar JSON: {columns, rows, rowCount, totalCount}. rowCount is the rows in this page; totalCount is the total matching records ignoring limit/offset. Columns: prompt_id, chat_id, model_id, model_channel_id, date, query_index, query_text.

list_shopping_demand

ChatGPT
Rank the query terms that drive shopping demand by how many distinct chats they appear in, with a trend vs a comparison window. Returns an aggregated ranking, not per-chat rows — for the individual queries in each chat use list_shopping_queries or list_search_queries instead. kind selects what is ranked: - shopping_query: product fan-out queries - fanout_query: web-search fan-out queries - query_term: n-grams across shopping queries (n sets the width, default 2 = bigrams) mode selects how the ranking is ordered: - top: highest distinct-chat count now - trending: biggest gainers vs the comparison window - losing: biggest decliners vs the comparison window - new: appeared in this window only Columns: kind, text, distinct_chat_count, distinct_chat_count_previous (count in the comparison window), delta (change vs the comparison window).

list_shopping_performance

ChatGPT
List products or categories (via entity_type) ranked by shopping performance over a date range. Performance columns are visibility, win_rate, avg_position, and appearances, each with a period-over-period delta. order_by picks the ranking metric (visibility, win_rate, or appearances); mode selects which entities to surface: top = highest now, trending = biggest gainers vs the previous period, losing = biggest decliners.

list_shopping_queries

ChatGPT
List the product/shopping queries an AI engine fanned out to while answering prompts in a project over a date range. Each row represents one shopping sub-query and the distinct products returned for it in a given chat. Filters: - prompt_id: only queries from chats produced by this prompt - chat_id: only queries from this chat - model_id: only queries from this AI engine (chatgpt-scraper, gpt-4o, gpt-4o-search, gpt-3.5-turbo, llama-sonar, perplexity-scraper, sonar, gemini-2.5-flash, gemini-3.1-flash-lite-search, gemini-scraper, google-ai-overview-scraper, google-ai-mode-scraper, llama-3.3-70b-instruct, deepseek-r1, deepseek-v4-pro, claude-3.5-haiku, claude-haiku-4.5, claude-sonnet-4, grok-scraper, microsoft-copilot-scraper, grok-4, grok-4.3, grok-4.6, qwen-3-6-plus, qwen-3-7-plus, amazon-rufus-scraper, mistral-small-4, mistral-medium-3-5, muse-spark-1.2) - model_channel_id: only queries from this channel (openai-0, openai-1, qwen-0, openai-2, perplexity-0, perplexity-1, google-0, google-1, google-2, google-3, google-4, anthropic-0, anthropic-1, deepseek-0, meta-0, meta-1, xai-0, xai-1, microsoft-0, amazon-0, mistral-0, mistral-1) - topic_id: only queries from chats whose prompt belongs to this topic - tag_id: only queries from chats whose prompt carries this tag Use get_chat with a returned chat_id to inspect the full AI response that produced these sub-queries. Returns columnar JSON: {columns, rows, rowCount, totalCount}. rowCount is the rows in this page; totalCount is the total matching records ignoring limit/offset. Columns: prompt_id, chat_id, model_id, model_channel_id, date, query_text, products (array of product names).

list_source_tags

ChatGPT
List the tags a project puts on URLs and domains (source tags), e.g. affiliate, partner or a campaign name. A URL or domain keeps one classification and can carry any number of source tags. Source tags are separate from prompt tags (list_tags): use these ids for the url_tag_id and domain_tag_id filters of get_url_report and get_domain_report, and for update_source_tag_assignments. Returns columnar JSON: {columns, rows, rowCount, total_count}; total_count is every source tag in the project, ignoring limit and offset. Columns: id, name, color.

list_tag_groups

ChatGPT
List the user-defined tag groups in a project, each with its shared color and tag count. Use this to discover group names before filtering list_tags by group or before renaming/deleting a group. System groups (branding/intentType) are not included — they appear on tags via list_tags.

list_tags

ChatGPT
List tags in a project. Tags are cross-cutting labels that can be assigned to any prompt. Use this tool to resolve tag names to IDs before filtering (tag_id filter/dimension, list_prompts), and to label tag IDs from report output with their human-readable names before presenting results. Returns columnar JSON: {columns, rows, rowCount, totalCount}. rowCount is the rows in this page; totalCount is the total matching records ignoring limit/offset. Columns: id, name, is_system, group. The group column holds a system group for system tags or the user-defined group name for user tags (null if ungrouped). Pass group to filter to a single user-defined group; use list_tag_groups to discover group names. System tags (is_system=true) are maintained by Peec and auto-assigned to every prompt by its branding/intent classification — they cannot be created, edited, or deleted, but they can be assigned to prompts. A system tag's group is "branding" (branded / non-branded) or "intentType" (informational / commercial / transactional); these are mutually exclusive: a prompt carries exactly one tag per group, so assigning a system tag (via update_prompts) overwrites whichever tag that prompt already had in that group rather than adding a second. Filter on the existing system tags — never create your own branded/intent tags.

list_topics

ChatGPT
List topics in a project. Topics are folder-like groupings — each prompt belongs to exactly one topic. Use this tool to resolve topic names to IDs before filtering (topic_id filter/dimension, list_prompts), and to label topic IDs from report output with their human-readable names before presenting results. Returns the project's confirmed topics; pass include_suggested=true to also return topics still awaiting confirmation, which carry no prompts yet. Returns columnar JSON: {columns, rows, rowCount, totalCount}. rowCount is the rows in this page; totalCount is the total matching records ignoring limit/offset. Columns: id, name, is_suggested (boolean — always false unless include_suggested is set).

list_url_classifications

ChatGPT
List the custom URL classifications defined for a project. These complement the built-in classifications (Homepage, Category Page, Product Page, Listicle, Comparison, Profile, Alternative, Discussion, How-To Guide, Article, Review, Other) and can be assigned to URLs via assign_url_classification. Returns columnar JSON: {columns, rows, rowCount, totalCount}. Columns: name, color.

publish_cms_content

ChatGPT
Save accepted content suggestions to the connected CMS. Requires project-owner access and CMS publishing enabled. Always use mode draft first. Show edit_url and wait for the user to review the draft and explicitly approve live publishing in a subsequent message. Then use mode live with reviewed_draft_hash copied from draft_content_hash. A general request to publish does not skip review. Changed drafts, articles, or original pages require another draft review. get_cms_page returns current draft readiness. A draft published directly in the CMS becomes a separate live page and blocks further publishing until reconciled. Draft saves apply only accepted suggestions to authored source markup. Missing or ambiguous passages are skipped and listed. Conflicting wording stops the write: show expected and current, then send overwrite_conflicts only after the user agrees, with content_hash and content_version copied from that response. Never invent current_text. Stale confirmations are refused. Use get_cms_drift and sync_cms_content to reconcile the article with CMS wording. Returns {data}: status (published, conflicts, stale, or failed), mode, page_url, edit_url, draft_content_hash on a preserved draft, applied_count, skipped_count, already_applied_count, overwritten_count, reverted_count, can_revert, was_filtered, failed suggestions, and unmodelled_ids. Report skipped suggestions and filtering to the user. WordPress validates proposed HTML using a temporary draft before updating an existing page; failed preservation or cleanup stops the update.

read_doc

ChatGPT
Read the full markdown content of a single Peec documentation page. Pass the path returned by search_docs (e.g. 'metrics/brand-metrics/visibility'). Answer strictly from the returned content — never invent product behaviour, metric definitions, limits, or feature claims. Returns {title, path, url, content, videos}, where videos lists the page's YouTube explainer videos as {videoId, title} (pages may also carry Watch "…" links in the content). When a returned video is relevant to what the user asked — a walkthrough or explainer of the feature, metric, or workflow in question — PREFER embedding it over linking to it or describing it in text: put [youtube:<videoId>] on its own line at the point in your reply where the video belongs, and it renders inline. Copy the videoId exactly from this tool's result — never guess or invent one, and never embed a video that did not come from this tool. Don't embed the same video twice, don't pad the answer with tangential videos, and skip embedding only when no returned video is relevant. No project context or auth required.

request_agent_readiness_audits

ChatGPT
Queue Peec's agent readiness audit for up to 50 of the project's own brand domains, so get_agent_readiness reflects the site as it is now. Returns: {created?: [{domain, run_id}], skipped?: [{domain, run_id, reason}], rejected?: [{domain, reason, message}]} - Only the project's own brand domains can be audited, passed exactly as get_agent_readiness lists them in own. Any other domain is rejected with reason not_own_domain; the rest of the call still goes through. - A domain whose audit is already queued or running is skipped with reason in_progress and that run's id; no second audit is queued. - Audits run in the background. Tell the user the audit has started, and read the result later with get_agent_readiness, whose latest_run for the domain carries the same run_id and its status; the result is not available in this call's response. Peec already audits every own and competitor domain on a schedule. Use this only when the user wants a fresh audit now, such as after changing their site. To read the latest audit, use get_agent_readiness.

resolve_optimize_content_suggestions

ChatGPT
Apply or dismiss the suggestions on a content-optimisation action, up to 50 in one call. Read the ids with get_optimize_content first — they are not in get_action, and kind says which of these a suggestion can take. action: - accept — take the suggestion's wording into the article. Only a rewrite carries wording; accepting an edit, which only names what is missing, resolves it without changing a word. - reject — dismiss it, leaving the original wording. - revert — put an accepted or dismissed suggestion back to pending. Only for suggestions Peec generated: an edit the user typed themselves is undone in the editor, not here, so reverting one is an error rather than a silent no-op. Every id that changes lands in one revision, so the call applies as a whole and the article's version moves once. It is the same edit the user makes with Apply and Dismiss on the Optimize content screen, and it shows in the article's history under their name. An id already in the state you asked for is left alone and counted in unchanged, so nothing is written when the whole batch already agrees. An id that is not on this action is an error, and nothing is written. Returns score (the optimisation score out of 100 after the change), unchanged, and suggestions (every id's resulting state). Re-read the article with get_optimize_content afterwards if you need its new wording — this does not return it. This rewrites the customer's live article, so name the suggestions you are about to apply in the sentence before you call it. Resolve what they asked for and nothing more — sweeping up every pending suggestion because they approved one is not what they agreed to.

search_docs

ChatGPT
Search the Peec docs (https://docs.peec.ai) and return the most relevant pages. The docs carry two kinds of content: product documentation (what a metric means, how a feature behaves, setup steps, plan/credit rules, 'how do I…') and Peec's published GEO/AI-search research under research/ (citation benchmarks, query fan-outs, engine behaviour, content strategy — each page names and links the original public study it republishes). Use this for product questions and for AI-search/GEO strategy questions alike, then call read_doc on the best result to read it in full before answering. Returns columnar JSON {columns, rows, rowCount}. Columns: title, path, url, snippet. Pass the returned path to read_doc. No project context or auth required.

set_brand_social_channels

ChatGPT
Replace the complete social-channel list for up to 50 brands. Each channel is supplied as its platform and full profile or community URL. Existing channels omitted for a brand are removed; an empty channel list removes all of that brand's channels. Confirm the exact replacement lists with the user before calling. Returns an updated count plus skipped or rejected brands.

set_project_profile

ChatGPT
Set the project's own brand-identity profile — its industry, target audience, tone, and similar descriptive fields. This is the project's own identity, not the competitor/monitored brand entities managed by update_brand/update_brands. All fields are required — the whole profile is overwritten, so first call get_project_profile, merge your changes into the existing values, then send the complete profile here. Saving triggers a background refresh of prompt suggestions. Confirm changes with the user before calling. Audience distribution percentages must sum to 100. The project's display name is not part of the profile and cannot be changed via this tool. Returns { success: true } once the profile is saved.

sync_cms_content

ChatGPT
Reconcile Peec's working article with changes made on the connected CMS page. Read get_cms_drift first and copy its content_version and content_hash. This updates the working article only; publishing to the website remains a separate action. Pass the user's reviewed choices in decisions (target 40 or fewer, maximum 50). Use cms to take the page's current wording and dismiss the old suggestion, or suggestion to keep the working article unchanged. Use remove only after the user confirms that a missing passage should be removed from the working article. Missing means the passage could not be located; it does not prove deletion. Copy its expected wording exactly. Never remove a passage merely because a search could not find it. When get_cms_page reports publishedExternally, show the original and separately published page URLs. Ask which should receive future updates. After the user's explicit choice, send external_publication with destination original or published and review_token copied from that read. Omit the text-sync fields. This preserves both site pages and the working article, clears the blocked draft, and requires a fresh draft review before any live write. If the original is missing, only published is available. A generic request to fix a conflict is not a destination choice. Returns status reconciled and page_url on success. Changed passages without suggestions sync automatically. Unreviewed suggestions and missing passages remain unresolved. The results array includes each action_id, status, content_version, content_hash, synced_count, conflicts, and missing; re-read get_cms_drift and get_optimize_content after a successful sync. A stale response requires a fresh review, not an automatic retry.

unarchive_prompts

ChatGPT
Unarchive up to 50 prompts (sets is_archived = false), reactivating them so they resume running. Subject to the project's active-prompt plan limit — prompts that would exceed it are rejected. Returns a count of reactivated prompts plus any skipped (not found) or rejected (plan_limit) items. Confirm with the user before calling.

unassign_domain_classification

ChatGPT
Clear the classification override on a whole domain (operates on a domain, e.g. "example.com" — for a single URL use unassign_url_classification), restoring the heuristic classification. Does NOT delete the custom classification entity itself (use delete_domain_classification for that). Confirm with the user before calling. Returns { success: true } once the override is cleared.

unassign_url_classification

ChatGPT
Clear the classification override on a single URL (operates on one full URL — for a whole domain use unassign_domain_classification), restoring the heuristic classification. Does NOT delete the custom classification entity itself (use delete_url_classification for that). Confirm with the user before calling. Returns { success: true } once the override is cleared.

update_action_steps

ChatGPT
Record which of an action's steps are done, across up to 50 actions in one call. Call get_action with fields ["steps"] first to read the step and option ids — they are not in list_actions, and an id from an earlier read can be stale. Each entry names one action and either sets completed for every step it holds, or lists steps. A step in turn either sets completed for all of its options, or names options individually, each with its own completed, so one call can tick some and untick others. Setting completed and listing parts on the same level is rejected. false puts a step or option back to not-done, so a step marked off by mistake can be corrected. Setting a value that is already stored changes nothing. An action is all or nothing: anything that cannot be applied leaves every step on it untouched, so you never have to read an action back to find out what landed. Other actions in the same call still go through. A CONTENT_OPTIMISATION action is reachable only on a project with content optimisation enabled; elsewhere it comes back skipped, as an action the project does not have. Returns updatedCount plus any skipped/rejected items, keyed on action_id. The action's own status is never changed here: it moves through its lifecycle in the Peec app, so completing every step does not mark the action COMPLETED. Skipped: not_found. Rejected: step_not_found or option_not_found (usually an id from before Peec regenerated the action — read it again), duplicate_id or duplicate_step_id (the same action, or the same step within one action, more than once in this call), not_completable (the action is a content brief, whose steps are the material it was written from rather than work to do). This records work a person has already finished; it does nothing to the pages the engines read. Confirm with the user before calling — it mutates project data.

update_actions

ChatGPT
Rewrite the fields a customer owns on up to 50 actions — the title, the description, the notes, the steps, who it is on and when it is due. It works on an action the customer wrote and on one Peec generated alike: an edit is kept beside the generated wording rather than in it, so a later regeneration cannot discard it. A field left out keeps what it held, and null clears the ones that can be cleared. An item naming no field beyond its id is rejected, so send the fields you want the action to end up with. steps replaces the whole list rather than merging into it, so send every step you want the action to end up with; to tick one off without rewriting the list, use update_action_steps instead. Write every step field in English regardless of the conversation language: the section heading (section), step title and step description. Moving an action to a different status is update_actions_status. Only an action the customer wrote can change kind: the type and group of a generated one say what Peec found, and an item trying to move them is rejected. A CONTENT_OPTIMISATION action is reachable only on a project with content optimisation enabled; elsewhere it comes back skipped, as an action the project does not have. Returns a count of updated actions plus any skipped (no such action in this project) or rejected items. Confirm the new wording with the user before calling.

update_actions_status

ChatGPT
Move up to 50 actions to a status, the same ones the Actions page writes: ACCEPTED to take one on, REJECTED to decline it, COMPLETED to record that the work is done, PENDING to put a resolved action back on the undecided pile, DELETED to take it off the list altogether. Complete an action only once the change is actually live on the page — the status is what the customer reads to know where the work stands, and it does not itself affect visibility. An action that is already deleted reads as absent to everyone but a platform admin, so a second call naming one comes back skipped. A CONTENT_OPTIMISATION action is reachable only on a project with content optimisation enabled; elsewhere it comes back skipped, as an action the project does not have. Returns a count of updated actions plus any skipped (no such action in this project) or rejected items. Confirm with the user before calling.

update_brands

ChatGPT
Update up to 50 brands in one call (name, regex, aliases, domains, color per item). Before changing aliases, read the brand's regex and aliases with list_brands. A nonempty regex is the active Advanced RegEx and overrides name and alias matching. Explain that aliases will not affect matching while it is active and ask whether the user wants to clear or change it before including regex in an update, unless they already requested that specific change. Approval to update aliases does not authorize clearing RegEx. Changes to name/regex/aliases trigger background metric recalculation per brand; updates during an ongoing recalculation are rejected. Read the saved settings back before confirming success, and do not claim Visibility changed without reading the resulting metrics. Returns a count of updated brands plus any skipped/rejected items (successful items are not echoed back).

update_categories

ChatGPT
Rename and/or move categories by id (use list_categories to resolve ids). Each item sets name (rename it), parent_id (move it under that category, or null to promote it to the top level), or both. Returns per-item results { updated, rejected } — the batch never fails as a whole. Rejection reasons: not_found, name_conflict (a sibling already has that name), invalid_move (would nest a category inside itself). Confirm with the user before calling — this mutates project data.

update_facts

ChatGPT
Update the wording or active state of up to 50 facts in one call. Changing text creates a new version while preserving the old wording for historical verdicts. Setting is_active=false keeps the fact visible but excludes it from future fact-checking. Returns an updated count plus skipped or rejected items. Call list_facts first, then confirm the exact changes with the user because facts are shared project data.

update_products

ChatGPT
Update up to 1000 products by id in one call (use list_products to resolve ids). Per item, set any of: name (unique within the brand), description, image_url, price_override (per-currency; replaces all overrides, {} clears them), category_ids (replaces the product's categories, [] uncategorizes it; use list_categories to find category ids). Omitted fields are left unchanged. Returns per-item results { updated, skipped, rejected } — the batch never fails as a whole. An item with nothing to apply is skipped (not_found / no_changes / duplicate_id); an unsatisfiable change (name conflict, unknown category) is rejected. Confirm with the user before calling — this mutates project data.

update_prompt_suggestions

ChatGPT
Edit up to 50 pending prompt suggestions from list_prompt_suggestions before finalizing: rewrite the text and/or replace the tag set per item. Prefer this over rejecting and regenerating when a suggestion is close but not quite right. Editing keeps a suggestion pending — accept it with finalize_prompt_suggestions to create the tracked prompt. tag_ids fully replaces the item's tags and must be existing tag ids from list_tags; system tags keep at most one per group, the last one passed wins. Returns a count of updated suggestions plus any skipped/rejected items (successful items are not echoed back).

update_prompts

ChatGPT
Update the topic, tags, location and/or fact-checking selection of up to 50 prompts in one call. Per item, pass tag_ids to fully replace the prompt's tag set, topic_id = null to detach its topic, country_code to move the prompt to another market while keeping the prompt and its chat history, or is_fact_checking_enabled to enable or disable fact-checking. Topic and tag ids must already exist. Moving a prompt to a market the project does not already track takes one of the plan's location slots, unless the prompts leaving their old market in this call are the last ones tracking it, in which case that slot pays for the move; items that would leave the project over the limit come back rejected with reason "limit_exceeded". Returns a count of updated prompts plus any skipped/rejected items (successful items are not echoed back).

update_source_tag_assignments

ChatGPT
Add and remove source tags on up to 50 URLs and 50 domains in one call. Tags are additive: a URL or domain keeps its classification and every other tag. A URL tag covers every variant of the URL that normalizes to the same address; a domain tag applies to the registrable domain, so blog.example.com and example.com share tags. Removals apply before additions, and adding a tag already present is a no-op. Get tag ids from list_source_tags, or create them with create_source_tags first. Returns how many tag assignments were added and removed; adding a tag already present or removing one that is absent counts as no change.

update_source_tags

ChatGPT
Rename or recolor up to 50 source tags (the tags on URLs and domains). Returns a count of updated tags plus any skipped items, such as a name another source tag already uses.

update_tag_groups

ChatGPT
Rename and/or recolor up to 50 user-defined tag groups in one call. The change applies to every tag in each group. Per group, provide a new name, a new color, or both (a group with neither is rejected). Returns each updated group with its affected tag count, plus any skipped (not found) or rejected items. Confirm with the user before calling.

update_tags

ChatGPT
Update up to 50 tags in one call (name, color, and/or group per item). Set a tag's group to move it into a group (inherits the group's color), null to ungroup, or omit to leave unchanged. Returns a count of updated tags plus any skipped/rejected items (successful items are not echoed back); system tags are skipped.

update_topics

ChatGPT
Rename up to 50 topics in one call. Returns a count of updated topics plus any skipped/rejected items (successful items are not echoed back).

get_brand_report

Claude

get_domain_report

Claude

get_url_report

Claude

list_brands

Claude

list_projects

Claude

list_prompts

Claude

list_tags

Claude

list_topics

Claude

App Stats

129

Tools

1

Prompts

ChatGPT, Claude

Platforms

Works with

ChatGPT
Claude

Data refreshed daily