- Brand
- 3RD
- Category
- Data & Analytics
- Primary Subcategory
- AI Search & LLM Visibility (AEO/GEO)
Integration details
Description
3RD measures how visible your brand is when people ask AI assistants about your market. Connect your 3RD account to ask, in plain language: - How visible is our brand right now, and how has that changed? - How do we rank against the competitors we track? - Which websites and pages do the assistants cite when they answer? - Which questions do we lack content for? - What should we do next, according to our plan and the recommended tasks? The plugin reads the brands, prompts, markets and competitors you already monitor in 3RD; it only shows data your account can access. Numbers cover a stated period, usually the last 30 days. The plugin only reads; it never changes your account. Monitoring is set up in the 3RD app; new brands and prompts need their first answers collected before results appear.
- Integration type
- Plugin
- Verification status
- Not applicable
- Platform
- ChatGPT
- Primary Subcategory
- AI Search & LLM Visibility (AEO/GEO)
- Secondary Subcategories
- None listed
- Brand
- 3RD
- Access
- Account required
- First tracked
- 2026-10-22
- Tool count
- 144
- Market
- US
The Primary Subcategory used for this profile’s headline score.
Other Subcategories where the Integration is listed.
Your score is coming
ChatGPT now suggests Plugins on its own when they match a user's request.Your Plugin Discovery Score measures how often yours appears, and it will show here as soon as it’s ready.
What discovery looks like

Get alerts for 3RD
Get updates when 3RD’s Discoverability Score or category rank changes.
Competing in ChatGPT AI Search & LLM Visibility (AEO/GEO)
View Category144 tools agents can invoke
List the AI assistants a brand can be monitored in (ChatGPT, Gemini, Claude, Perplexity, AI Overview/Mode and the rest), which of them are currently enabled, and the plan allowance (limit / remaining). Read this before set_ai_models — its modelId and name values are what that tool accepts.
list_ai_models
Reads back the dashboard filters (page, date range, prompt types, topics, models, markets) the current turn is actually scoped by — the same scoping already described to you in prose above. Takes no arguments: filter state arrives only through the signed session claim, never as a tool argument, so calling this with any input has no effect on what it returns. A dimension the claim had to drop for size is named in `omitted` rather than reported as an empty or 'all' selection. DEPRECATED since 2.4.0: this tool will be removed after 2026-12-24.
get_active_filters
Get full reporting for ONE ad campaign — the campaign detail page over MCP. Returns the campaign with its metrics plus three breakdowns: `dailySeries` (per day: impressions, clicks, spend, conversions), `countriesBreakdown` (per country: the same four), and `adGroups` with their creatives (per ad group and per ad: impressions, clicks, spend, conversions, plus each creative's title, body, target URL and review status). This is the ONLY ad tool with measured `conversions` (and therefore a meaningful `cpa`) — they come from a separate conversions endpoint the list and daily tools do not call. Get campaign ids from list_ad_campaigns; a campaign belonging to another brand reports as not found. Optional `breakdowns` (daily, countries, creatives) trims the response. Same fixed trailing 30-day window and EUR figures as list_ad_campaigns. Note that the per-day and per-country rows carry no conversions either — only the campaign total does.
get_ad_campaign_performance
List the brand's OpenAI Ads campaigns with their delivery metrics — the rows behind the /ads page. Per campaign: id, name, description, status (draft, pending-review, scheduled, active, paused, completed, archived, rejected), startDate/endDate, lifetimeBudget, dailyBudget, targeted countries, the linked 3RD prompt or topic, and metrics { spend, impressions, clicks, conversions, ctr, cpa }. `totals` is the brand's rollup across every NON-ARCHIVED campaign and ignores the status filter and limit, so it always matches the /ads page headline. Metrics cover a FIXED trailing 30-day window ending yesterday (see dateRange) — `spend` is spend in that window, not lifetime spend — and money is in EUR, converted from the USD account. `conversions` is NOT measured on this tool (it is not part of the insights projection, so it reads 0 either way, making `cpa` meaningless here) — see `conversionsNote` and use get_ad_campaign_performance for real conversions. Optional `status` filters the listed campaigns; `limit` caps them (default 50, max 100) and `limitReached` says when more matched. When OpenAI Ads is not connected for the deployment, `connected` is false and the reason is in `note`.
list_ad_campaigns
Get the brand's ad delivery day by day: `series` sums every reported campaign onto one date axis (impressions, clicks, spend, conversions, plus ctr derived from that day's summed counts), and `campaigns[].days` gives the same per campaign — the campaign × date grain to load into your own warehouse or BI tool. Archived campaigns are excluded unless you name them in `campaignIds`; pass `includeCampaignBreakdown: false` for the merged series only. Costs one upstream request per campaign, so at most 25 campaigns are reported per call — `campaignsCapped` says when there were more, `unknownCampaignIds` lists requested ids the brand does not own, and `failedCampaignIds` lists campaigns whose series could not be read (they contribute nothing rather than zeroes). Same fixed trailing 30-day window and EUR figures as list_ad_campaigns, and `conversions` is likewise NOT measured here (see `conversionsNote`).
get_ad_daily_performance
Get the brand's ad wallet position — balance, committed reserve, whether it is in arrears, the pause floor and spend so far this month — plus its recent statement. Returns the SAME figures as the Ads Billing page (GET /api/ads/wallet); report them verbatim. `provisioned: false` means either no wallet has opened yet or (when `reason: "own_account"`) the brand is billed through its own ad account — never report either state as a zero balance. Read-only: this tool cannot start a wallet top-up.
get_ad_wallet
Create a new brand in an organisation — the same brand the app's Create-brand dialog creates. Requires brandName, url (the brand's own website) and country (ISO 3166-1 alpha-3) for its first market; optional languages (ISO 639-3, defaults to ["eng"]), industry, competitors ([{name, url}]) and aiModels (assistant names or ids from list_ai_models — omitted seeds the plan's defaults). orgId picks the organisation — it must be a real org id (from list_brands' orgId field), never an org name; omitted, the key's own organisation is used. A missing/invalid orgId, or one you cannot write to, is refused with a hint naming the organisations you CAN write to (name + id) — retry with one of those. The brand arrives with its market, seeded AI models, its own domain tracked and a daily analysis run scheduled — but with NO prompts, so follow up with add_prompts. Creating a brand on a URL the account already tracks returns that brand instead of a second copy; a duplicate brand NAME is refused. Requires write rights in the organisation and room in the plan's brand allowance.
add_brand
Add one or more brand attributes — the same list the Brand Profile's attributes card edits. Pass every attribute to add in one call (1-10 per call); each is added once, matched case-insensitively against attributes already on the brand, so re-sending one already present confirms it rather than duplicating it. Confirm the exact wording with the user first. Requires write access to the brand.
write_brand_attributes
Add one or more brand objectives — the same list the Brand Profile's objectives card edits. Pass every objective text to add in one call (1-10 per call); each is added once, matched case-insensitively against objectives already on the brand, so re-sending one already present is a no-op rather than a duplicate. Confirm the exact wording with the user first. Requires write access to the brand.
write_brand_objectives
Track a competitor on a brand — the same competitor the Settings → Competitors modal creates. Requires name; url (the competitor's website; bare hosts like "competitor.com" are fine) is optional. Omit url for a competitor with no website — it is still matched on brand-name mentions in AI answers, but domain-based metrics like citation share stay empty for it. Optional urls adds further domains the same company owns — they are folded onto ONE competitor identity, so every host counts toward it. Optional aliases lists other names the models may use for it; optional countryCodes (ISO alpha-3) limits it to specific markets (omit for all of them); optional topicIds limits it to specific topics (omit for all). Adding a competitor re-counts its share of past answers in the background, so competitor metrics keep moving for a few minutes. A duplicate name or domain (with or without https:// or www.) is refused. Returns the new competitor's id and its stored aliases. Requires write access to the brand.
add_competitor
Create monitored prompts on a brand — the questions the AI models are asked on every run. Pass 1-25 prompt texts (each 5-2000 chars, phrased as a user would ask an AI assistant, in the market's language). Optional topicId (from add_topic or the topics in get_topic_mentions) attaches them to a topic; optional country (ISO alpha-3, e.g. DNK) scopes them to one market — omit it to default to all the brand's markets; optional language overrides the default; optional tags (tag names, or ids from list_tags) go on every prompt created — an existing tag is reused ignoring case and a new name creates the tag, as the app's CSV import does. Prompts are classified (must-win/core/foundation) automatically and queued to run immediately, so first responses land within minutes. Counts against the plan's prompt allowance (get_plan_usage prompts.remaining says how many more fit); requires write access to the brand.
add_prompts
Add one or more sections to a report that already exists — the way a chart the assistant just drew gets kept, by naming the report module that builds the same view. Pass reportId from list_reports and the section keys. Append-only: it never removes a section, because a report people receive by email can be quietly emptied that way. A section already on the report is reported as such rather than duplicated. Requires write access to the brand.
add_report_section
Create a custom tag on a brand, for organising its monitored prompts. The name (1–40 characters) must be unique per brand, ignoring case — a duplicate is refused; call list_tags first. Optional `color` is a palette key (default gray). The tag starts on no prompt — call tag_prompts with the returned id to attach it. Requires write access to the brand — read-only members are refused.
add_tag
Create a task on the brand's playbook — the board the team works from. Use it to turn an answer into work someone will actually do: pass a title (4-200 chars, an action rather than a topic) and a description carrying the reasoning and the figures behind it, so the task still makes sense to someone who did not see the conversation. Optional priority (high/medium/low, default medium). The task is recorded as coming from the assistant, so its origin is recoverable later. Requires write access to the brand. Optional, as on the board's Add-task dialog: `instructions` (checklist steps), `playbookId` (from list_strategic_initiatives) to put it in a playbook, `marketIds` (from list_markets_audiences; [] = all markets), `impactScore` (0-100) and `assigneeUserId` (an org member). To add a suggested task, pass its `suggestionSourceKey` from list_suggested_tasks (and the `suggestionMarketId` you listed with, if any) instead of a title: the task is created exactly as the Recommended rail's Add creates it — same brief, steps, page and market — and the suggestion leaves the rail. A playbook whose market differs from the task's is refused unless `confirmMarketMismatch` is true.
add_task
Create a new topic on a brand. Topics group the brand's monitored prompts (they drive the Topics leaderboard and per-topic filters). The topic is created EMPTY — call add_prompts with the returned topic id to seed prompts under it. The name must be unique per brand (case-insensitive; a duplicate is refused). Optional description, and optional marketId (a UUID from list_markets_audiences) to scope the topic to one market. Requires write access to the brand — read-only members are refused.
add_topic
The brand's own pages that fail one technical check — the list a technical task shows in the app, from the same lookup. Pass `taskId` (a task with sourceType domain_signal, from list_tasks) or `check` (a check name from get_agent_readiness with findings: true, e.g. "Image Alt Text Coverage"); optional `domainId` keeps one site, `limit` caps the URLs (default 100, max 500). Returns the failing URLs, how many pages were analysed and the URL templates they share.
get_affected_pages
Get agent readiness, SEO and Core Web Vitals for the brand's own pages: the average of each score across the brand's tracked, analyzed pages, and the best and worst pages. Optional fromDate/toDate (YYYY-MM-DD) keep pages analyzed in that range; marketId keeps one market. Pass `findings: true` to add the page's Issues tab per own site (`domains[].findings`): each serious issue with its check, stage, severity, what was found, how to fix it, pages affected out of pages analysed, whether one site-wide fix solves it, the URL templates it sits on and sample URLs — the technical to-do list to hand to IT. Findings cover each whole site (every market, no date window), as the page does with all markets selected; get_affected_pages lists every failing URL for one check or task.
get_agent_readiness
SUPER-ADMIN ONLY. The AI answers behind any report_visibility or report_citations row, across up to 100 brands, read from ClickHouse and paged with a cursor. Use it instead of calling get_prompt_responses once per brand, and to read or classify every answer in a slice. Returns { columns, rows, rowCount, totalRows, nextCursor, window, dataThrough, definitions }: one row per answer, an array in column order; definitions gives one sentence per column; totalRows is the whole listing's size; dataThrough is when its newest answer was generated. Columns: answer_id, brand, brand_name, created_at, model, model_name (the assistant), market, market_name, country, language, prompt, prompt_text, prompt_type, topics, topic_names, mentioned, position (null when the brand is not ranked), sentiment, citations (count); add text with includeText, the distinct cited URLs with includeCitedUrls, and the assistant's web searches with includeFanoutQueries. Window: fromDate and toDate (YYYY-MM-DD, UTC, both inclusive, required), at most 400 days apart and not capped to the last 90 days. The answers are the answers export's (export_prompt_responses, start_export answers): error and count-less answers are left out, and an answer counts when it has no prompt or one of its brand's active prompts; branded prompts are included. filters: [{ field: model|market|audience|topic|prompt|prompt_type, op: in|not_in, values }], all must hold, exactly as in report_visibility, so the filters of a report row list that row's answers. mentioned: true or false keeps only answers that do or do not mention the brand. Order: brand by brand, newest first within each brand. Paging: limit answers per page, default 1000 and max 5000, or default 50 and max 200 with includeText. Pass nextCursor back unchanged, with the same brandIds, window, filters and mentioned, for the next page, until it is null; a page can hold fewer than limit answers when they are large. Every page of one listing reads the same snapshot, which ends five minutes before the first page was requested. Errors: a brand the caller cannot read fails the whole call. If ClickHouse is unavailable, fails or times out, the call returns an error saying so and never answers from another store; on a timeout, narrow the listing.
list_answers
Apply a section change that preview_page_sections worked out: start tracking addUrls and stop tracking dropUrls on one of the brand's own sites, in one step. Pass the two lists and selectionRevision exactly as the preview returned them (at most 500 pages each); the user confirms the change before anything is written. Refuses, and changes nothing, if the tracked pages changed since the preview, if it would leave the site with no tracked page, or if it would go past the plan's page allowance. Requires write access to the brand.
apply_page_sections
Get owned-citation share per AI assistant for a brand over a date range (default last 30 days); assistants that share a vendor, such as AI Overview, AI Mode and Gemini, are separate rows (the row's field is still named provider). Provide fromDate/toDate (YYYY-MM-DD) to scope the window. Matches the dashboard Attribution by provider card.
get_attribution_share
Fetch a brand profile for the authenticated tenant. Pass brandId (from list_brands) — that resolves exactly one brand. brandName and/or brandUrl also work as a substring lookup when you have no id, but either one alone is enough, and a name the tenant does not own returns not-found rather than a near match — so prefer the id. Returns brandId (pass it to every other brand tool), name, domain, siteUrl — the brand's main tracked website as a URL, "" when it tracks none; prefer it over domain — trackedDomains — the brand's own-brand tracked domain names, the set used for owned/earned citation classification — markets, categories, competitors (the names of the competitors the brand tracks, as list_competitors lists them), isInternal — true when the brand belongs to a 3RD-internal/test workspace rather than a customer — brandName (the canonical name answers are matched on), displayName, aliases (the brand's own alternative names, also matched), countsBrandedInVisibility (false: prompts that name the brand are left out of visibility, the default), brandedPrompts (branded and active prompt counts and sharePct, the percentage flagged branded) — completeness, a set of booleans (industry, description, voice, objectives, worldview, attributes) that are true when that part of the profile is filled in and false when it is still empty — and the profile's current content: industry, description and voice (null when empty), desiredWorldview (positioning, categoryAmbition, keyAssociations, proofPoints, avoidances, mainCompetitors, offerings, excludedTopics; null when never set), attributes (each with id, attribute, source and confirmed — only confirmed ones count on the profile) and objectives (each with id, text, goalType, isActive and marketId, null for every market). Read these before overwriting any of them.
get_brand_profile
Produce the content brief for one prompt from get_content_gaps — the SAME brief the Content page shows when the prompt is opened, in the caller's own locale. Pass promptId; optionally contentType (one of the row's contentTypes ids) and targetUrl (the row's primaryTarget or an alternativeTargets url) — omitted, the row's recommended content type and primary target are used, as for content tasks. promptText and topicName are accepted for older callers and ignored. Populates the shared brief cache and runs a model call, so it asks first. Feed the returned brief into generate_page's brief argument to write the page.
brief_content_gap
Produce ONE brief that optimises one of the brand's own pages for several prompts at once — the edits to make so the page answers all of them, not a rewrite. Pass the page's pageId (from get_site_structure) and promptIds: 1 to 5 prompt ids, usually ones get_page_prompts lists for the page. The brief is grounded in the page's current content, each prompt's fan-out queries and the pages AI cites for it. Each edit in structure lists the promptIds it serves; prompts repeats the chosen prompts and their text; ownPagePromptIds lists any prompt no edit serves because it needs a page of its own; fanoutQueries lists the target keywords, the fan-out queries of the prompts the edits serve, each with how many answers ran it, most-run first. Returned in the caller's own locale. Populates the shared brief cache and runs a model call, so it asks first; the same page and prompts return the cached brief.
brief_page_for_prompts
Track a batch of page URLs for a brand in one call — the assistant's twin of pasting a list of URLs in. Every URL must be on one of the brand's own tracked domains; if any URL is off-domain, the whole batch is refused with a VALIDATION_ERROR naming the domain rule rather than silently dropping it. Already-tracked URLs are left unchanged rather than re-added. Requires write access to the brand.
bulk_add_pages
Start or stop tracking pages on a brand, by page id from list_monitored_pages or by page URL. A URL may name a page the brand has only seen in its sitemap; it must be listed in the sitemap of one of the brand's tracked domains. Tracked pages are the ones that get scraped, scored and watched for citations, and the count is capped by the plan — so tracking more usually means untracking something. Pass pageIds and/or urls (1-500 in all) and isTracked. Refuses if it would leave one of the brand's tracked domains with no tracked page, or go past the allowance. Requires write access to the brand.
set_page_tracking
Get the FIRST date each given URL started appearing as a citation for the brand (plus the most recent date and total citation count). Answers 'when did this URL first show up as a citation?'. Pass the exact URLs to look up; they are matched after the same normalization applied at citation time (query string + fragment stripped), so tracking params are ignored. Not date-windowed — scans the brand's full citation history. URLs never cited return cited=false with null dates.
get_citation_first_seen
One citation table across up to 100 of the brands you can read, in a single call, read from ClickHouse. Use it instead of calling get_citation_sources or get_citations once per brand. Returns { columns, rows, rowCount, totalRows, nextCursor, window, dataThrough, definitions }: each row is an array in column order; every id dimension (brand, model, market, topic, prompt) is followed by its label column (brand_name, model_name, market_name, topic_name, prompt_text); definitions gives one sentence per requested metric; dataThrough is when the newest citation in the report was recorded. Window: fromDate and toDate (YYYY-MM-DD, UTC, both inclusive, required), at most 400 days apart and not capped to the last 90 days. A citation belongs to the day it was recorded, as on the Citations page. Metrics: citations, citation_share, answers_citing, owned_share, first_seen, last_seen (default citations + citation_share). Numbers match the Citations page's source table for the same brand, window and filters, with owned and earned sources both counted. Dimensions (default brand, at most 4, at most one of day/week/month; [] gives one total row): brand, domain, url, model (one row per assistant covering all its versions), market (null for prompts with no market), topic (a prompt in several topics counts in each, so topic rows can add up to more than the total; null for prompts in no topic), prompt, day, week (starting Monday), month. filters: [{ field: domain|url|model|market|topic|prompt, op: in|not_in, values }], all must hold. domain matches the host and its subdomains; model takes the modelId or name list_ai_models gives (an assistant name such as ChatGPT or AI Overview, any case) or a vendor name such as openai, widened to every version of the assistant as the dashboard does, and a value naming none of these fails with VALIDATION_ERROR; market, topic and prompt take ids. domain and url filters narrow the rows but leave citation_share a share of the brand's whole window. orderBy: [{ field, direction }] over requested dimensions and metrics; default the first metric descending. Paging: limit rows per page (default 1000, max 10000). Pass nextCursor back unchanged, with the same other arguments, for the next page, until it is null; a page can hold fewer than limit rows when the rows are large. Every page of one report reads the same snapshot, which ends five minutes before the first page was requested. Errors: a brand the caller cannot read fails the whole call, and so does a brand whose plan leaves out Citations, or caps it to its top sources when the report has a url dimension or filter. If ClickHouse is unavailable, fails or times out, the call returns an error saying so and never answers from another store; on a timeout, narrow the report (fewer brands, a shorter window, coarser dimensions).
report_citations
Get the DETAILED per-source citation list for a brand — the Citations Top Sources view. Each cited URL with its owned/earned kind, citation count, share, the prompts/providers/topics/competitors behind it, and brand-mention status. Use when the question is WHICH sources cite the brand (get_citations returns only the owned/earned share). Also the tool for 'which URLs/pages from domain X are cited' and 'which sources drive our must-win prompts': domain keeps only URLs on that host (or its subdomains) and promptType restricts to prompts of one category (must-win / core / foundation) — the answer is the per-URL list with the prompts behind each URL. Optional fromDate/toDate (YYYY-MM-DD) scope the window; kind filters owned/earned/paid. topicId (or topicIds for several) scopes to a topic's prompts and marketId / country (ISO alpha-3, e.g. DNK) to one market — these narrow WHAT IS COUNTED, so citations and share are that topic/market's, not the source's brand-wide totals, and match the dashboard with the same filters applied. Topic ids come from get_topic_mentions, market ids from list_markets_audiences. Paginated: limit is the page size (default 50, max 200) and page (1-based) selects the page; the response includes total, totalPages, hasMore and nextPage — call again with page=nextPage until hasMore is false to walk the full source list. High-volume brands: aggregating a wide window in one request can exceed the time budget; when it does the response comes back with timedOut:true, an empty sources array, and a chunkHint — narrow the window (e.g. one week at a time) and/or pass a single marketId, then page through each smaller slice. gap:true keeps only gap sources — pages that mention at least one tracked competitor while a check of the page's content found the brand absent (pages not yet checked are left out), off the brand's own site; every row then has brandMentioned false and a non-empty competitorsMentioned. The filter runs before pagination, so total counts gap sources only, while share stays a share of all the brand's citations. groupBy:'domain' returns domains instead of sources: per domain the citations, share, previousCitations, urlCount, brandMentionedUrlCount and the competitors mentioned (with how many of its URLs mention each), ranked by citations over the whole source list; limit/page then page through domains, and the domain citations add up to totalCitations. Combine gap and groupBy for a per-domain gap list. A source or domain row with competitorOwned (the competitor's name) is that tracked competitor's own site: never propose it as an outreach or placement target (the brand cannot get published there), though you may name it as a place where the brand loses visibility to that competitor.
get_citation_sources
Get citations where the brand is referenced, with each source URL classified as owned/earned/other and assigned a source category (Owned, Media, Institutional, Academic, Private Organizations, Non-profit, Knowledge, Social, Communities / UGC, Commerce, Other). Optionally filter by one or more categories. Optional fromDate/toDate (YYYY-MM-DD) scope the window — pass BOTH or neither; one alone is ignored and reads the last 30 days, as do no dates at all; whenever a date you passed was ignored or the window narrowed, windowNote says what was read instead. A toDate runs to the end of that day, and a window wider than 90 days is narrowed to the most recent 90 — the same rules the dashboard applies, so the two agree. topicId (or topicIds for several) scopes to a topic's prompts, and marketId to one market — both narrow WHAT IS COUNTED, so each URL's count is that topic/market's citations rather than the brand-wide total. Topic ids come from get_topic_mentions, market ids from list_markets_audiences. The totalCitations / ownedCitations / earnedCitations / otherCitations totals cover every cited URL in the scoped window and sum to totalCitations: owned = the brand's own pages, earned = other pages whose scraped content names the brand, other = the rest (not naming the brand, or not yet checked) — the same split as the dashboard Citations page; totalCitations and ownedCitations match the dashboard's Citation Share card for the same scope; `limit` slices only the returned items list; totalSources counts every cited source and hasMore is true when items holds fewer — use get_citation_sources to page through all of them. For per-source share, ranking and the topics/prompts behind each URL, use get_citation_sources — it reconciles with the dashboard Citations view.
get_citations
Which sources each prompt's answers cite — the Citations page's "Grouped by prompt" view. For each prompt in the window: citations (how many citations its answers had) and sources, each cited URL with owned (true for the brand's own pages), kind (owned, earned or paid), brandMentioned (whether the cited page mentions the brand; null until the page is checked), count (times cited) and share (of the prompt's citations, in %). Prompts are ordered by their latest answer and paged: limit prompts per page (default 20, max 50), page (1-based), with totalPrompts, totalPages, hasMore and nextPage; citationsPerPrompt (default 25, max 100) caps each prompt's sources, most cited first, and sourcesTruncated says when it cut some. fromDate/toDate (YYYY-MM-DD) fix the window; without them it is the last 90 days, as on the page. Optional marketId (list_markets_audiences), topicIds (get_topic_mentions), promptType and kind narrow what is counted.
get_citations_by_prompt
Say that a product in the shopping results is this brand's own (owned: true), or that one attributed to it is not (owned: false). Pass productId from get_product_visibility or list_unseen_products. A brand can only take a product no tracked brand holds, and only give back one attributed to itself — naming some other company as the maker is not possible here, and needs report_problem. The verdict is locked, so the nightly maker matching will not overwrite it. One product row is shared by every brand, so this changes what everyone sees. Requires write access to the brand.
set_product_owner
Get competitor ad placements observed against the brand's tracked prompts. Returns the SAME placements as the Competitor ads tab (GET /api/ads/competitor-ads) for the same window and filters; report them verbatim. By default (no `section`, or `section: "summary"`) it returns the tab's headline only: the summary figures, placement counts, how many rows each list holds (`sectionCounts`) and the filter options (the first 10 advertisers; `advertisersTotal` gives the count). Full rows come from `section` advertisers, bidders, topics, prompts, creatives or presence, paged with `limit` (default 25, max 100) and `offset`: follow `nextOffset` while `hasMore` is true. A page can hold fewer than `limit` rows when the rows are large. The tab's filters narrow every figure: `topicIds` (topic ids), `markets` (ISO alpha-2 country codes) and `advertiserIds` (ids from `filterOptions.advertisers` or the `advertisers` section). Optional `days` sets the window (default 30, max 180). When the brand lacks the ads-tracking entitlement, `available` is false and no ad data is returned.
get_competitor_ads
Get the brand-vs-competitor ranking by visibility score (brand + competitors sorted, each with score and rank, plus the brand own rank). Optional fromDate/toDate (YYYY-MM-DD) scope the window; without them this reports the last 30 days. Returns the SAME ranking as the dashboard Competitor rank card / Leaderboard (prompt-averaged visibility); report it verbatim. When branded prompts are excluded (the default), a prompt that names a tracked competitor or one of its aliases is left out of that competitor's visibility only. It still counts for the brand and for competitors it does not name, so each competitor has its own denominator. Filters, the same as the dashboard filter bar: marketId (ids from list_markets_audiences) or country (ISO alpha-3, e.g. DNK) for one market, counting only the competitors tracked there; modelId (ids from list_ai_models) for one assistant, every version of it counted; topicId or topicIds (ids from get_topic_mentions); promptType (must-win / core / foundation); tagIds (ids from list_tags), which with promptType match a prompt of that type OR with one of the tags. Dates are YYYY-MM-DD: a lone fromDate runs to today, a lone toDate covers the 30 days up to it, and a window longer than 90 days is cut to the 90 days ending at toDate. The numbers then equal the dashboard with the same filters.
get_competitor_ranking
Accept a suggested brand-context entry by itemId (from list_brand_context or suggest_brand_context): it becomes active with origin confirmed, and 3RD uses it from then on. In a statement section (one entry, e.g. description) the entry it replaces is marked outdated. Confirming an entry that is already confirmed is a no-op. Only a suggested entry can be confirmed. Requires write access to the brand.
confirm_brand_context_item
Get the brand's content recommendations — the same list, numbers and order as the Content page in the app (default view: every prompt, highest opportunity first). Per prompt: whether the brand's own pages cover it (coverage %, matching-page count, opportunity score), the recommended action (optimize an existing page, create a new one, or defend), the recommended content type and target URL, and the brand's visibility and citation share for that prompt — every field of the page's row except the per-format brief templates, cited pages and fan-out queries, which brief_content_gap returns for one prompt. Pass topicId to see one topic only. Pass marketId (a market UUID from list_markets_audiences) to get the list the Content page shows with that one market selected — that market's prompts plus the brand-wide prompts that carry no market; omitted, every market is included, as in the page's default view. The page's other filters take the same ids: tagIds (tag ids from list_tags) and promptTypes (must-win / core / foundation) are its Tags filter, where a prompt matches a selected category OR a selected tag; audienceIds (audience ids from list_markets_audiences) keeps the prompts of those audiences. For the brand's own pages that already answer one prompt — the page's Matching pages list — call get_matching_pages with the row's promptId. Coverage is a standing state of the brand's pages, not a windowed metric, so this takes no date range — do not report it under another tool's period. Paged like the page's table: `limit` rows per page (default 50, max 200) and `page` (from 1); `hasMore`/`nextPage` say when more rows remain, and `total` counts them all. `sortBy` is one of the table's columns (opportunityScore, coverage, matchingPages, volumeScore, promptText, promptType, topicNames; default opportunityScore) and `sortDir` asc or desc (default desc). Pass `compact: true` for the table's columns only (prompt, type, topics, tags, volume, coverage, matching pages, opportunity, action, content type, target URL, visibility, citation share), a small fraction of the full row, to read the whole list in fewer calls.
get_content_gaps
Get the brand's current-month content generation quota — limit, used and remaining. Returns the SAME numbers the content-agent usage view shows; report them verbatim. limit and remaining are null when the brand's plan is unlimited.
get_content_quota
Get citability-signal scores for a brand's own pages — definitive-language density, readability, front-loading, hedging, entity definitions, title quality, plus HTML-dependent heading/list/table signals when available. Returns the SAME aggregate the content-quality dashboard view shows; report it verbatim.
get_content_quality
Build a playbook (strategic initiative) the way the app's playbook builder does, in two steps. First call WITHOUT `confirm`: nothing is written; it returns the brand's scope choices (`scopeOptions`: markets, topics with prompts, AI models), where the brand stands on the goal metric (`estimate.currentScore`) with three suggested targets, and the plan — the actions the engine would put in the playbook for that scope and target (`tasks`, each with a sourceKey and a one-line why). Show the plan, take the person's changes (put a removed task's sourceKey in `excludedSourceKeys`; the freed slot refills), and preview again. Then call with the SAME arguments plus `targetScore`, `startScore` (the estimate's currentScore) and `confirm: true` to create it: the tasks land on the board at once and their briefs are written in the background. `goalType` is increase_visibility or improve_citation_share; `marketId` from list_markets_audiences; `topic` exactly as scopeOptions names it; `promptCategory` all/must-win/core/foundation; `modelIds` from list_ai_models ([] = every tracked model); optional `note` in the person's own words. Refused with PLAN_LIMIT_REACHED when the plan's live-playbook allowance is used. Requires write access to the brand.
create_playbook
Stop tracking a competitor — the same delete as the bin icon in Settings → Competitors. Identify it with `competitor`: its id, name, an alias or its domain, as list_competitors returns them. It drops out of every competitor metric from now on; answers already stored are not rewritten. To fold a duplicate into another competitor instead of losing it, use merge_competitors. Requires write access to the brand.
delete_competitor
Stop tracking one of a brand's markets in every language — the same delete as Settings → Markets. Pass marketId (any of the market's marketIds from list_markets_audiences). The market's prompts stop running and stop counting against the plan, and its answers are hidden but kept; re-adding the market with add_market brings the same prompts back with their history. To drop only one language, use edit_market with removeLanguages instead. The brand's last market cannot be deleted, and a market a draft or active playbook is set to is refused until that playbook is finished or moved. Confirm the market with the user first. Requires organisation owner/admin rights.
delete_market
Delete a playbook, as Delete on its page in the app does. Pass `playbookId` from list_strategic_initiatives. Its tasks stay on the board unless `deleteLinkedTasks` is true, which also deletes the tasks no other playbook holds (`deletedTasks` counts them). This cannot be undone through the tools — to stop work but keep the history, complete it with update_playbook instead. Requires write access to the brand.
delete_playbook
Delete a custom report, as Delete on the Reports page does; its scheduled emails stop with it. Pass `reportId` from list_reports. The ready-made default reports cannot be deleted — stop their emails with update_report and `recipients: []` instead. This cannot be undone through the tools. Requires write access to the brand.
delete_report
Delete one of a brand's saved skills by skillId (from list_saved_skills), the same delete as the chat's skill menu. It disappears for the whole team, in the app and as an MCP prompt. Requires write access to the brand.
delete_saved_skill
Delete one of a brand's custom tags by tagId (from list_tags) — the same delete as Settings → Tags. The tag comes off every prompt that carried it; the prompts themselves are kept. This cannot be undone through the tools. An AI Ontology (`system`) tag is refused. Requires write access to the brand.
delete_tag
Delete tasks from the brand's Task board, as the board's own delete does: a task the engine can suggest again is deleted (`deleted`), and any other — a custom task, an audit or brief task — is archived to icebox so its history is kept (`archived`). Pass up to 50 `taskIds` from list_tasks or get_playbook; an id that is not on this brand comes back in `failed`. Confirm the exact list first. Requires write access to the brand.
delete_task
Delete one of a brand's topics by topicId (from list_prompts, add_topic or get_topic_mentions) — the same delete as Settings → Topics, with its keep-or-remove choice. `deletePrompts: false` keeps the topic's prompts running with no topic; `deletePrompts: true` also removes its active prompts (they stop running and free room under the plan's prompt limit). This cannot be undone through the tools, so confirm the topic and the choice first. To stop tracking a topic but keep its data, use pause_topic instead: its prompts stop running and free room under the prompt limit, and resume_topic brings them back. An AI Ontology topic is refused. Requires write access to the brand.
delete_topic
Dismiss a suggested brand-context entry, or an inferred one that is wrong, by itemId (from list_brand_context). It stops being used and is not suggested again. An entry a person wrote or accepted is refused: change it in the brand profile instead. Dismissing twice is a no-op. Requires write access to the brand.
dismiss_brand_context_item
Dismiss suggested tasks so the engine stops suggesting them, as Dismiss on the Recommended rail does: it saves a rejection rule on the brand, so the suggestion disappears for every member, from the rail, the playbook builder and list_suggested_tasks. Pass up to 50 `sourceKeys` from list_suggested_tasks (and the `marketId` you listed with, if any). `scope` `task` (default) rules out just these suggestions; `host` rules out every outreach or authority suggestion on the same site — use it for "never suggest pitching competitor sites". Optional `reasonKind` and a free-text `reason` are kept with the rule. Nothing is dismissed if any sourceKey is not on the rail. Requires write access to the brand.
dismiss_suggestion
Confirm, unconfirm or delete one brand attribute on the brand profile, by the id get_brand_profile returns in `attributes`. Pass `confirmed` (true makes a suggested attribute count on the profile, false turns it back into a suggestion) or `delete: true` to remove it. To add attributes use write_brand_attributes. Requires write access to the brand.
edit_brand_attribute
Change or delete one marketing objective on the brand profile, by the id get_brand_profile returns in `objectives`. Pass any of `text` (new wording, at most 200 characters; it is re-classified into a goal type), `isActive` (false keeps it but stops it steering recommendations), `marketId` (a market id from list_markets_audiences, or null for every market) — or `delete: true` alone to remove it. To add objectives use write_brand_objectives. Requires write access to the brand.
edit_brand_objective
3RD ChatGPT Plugin FAQ
How the directory, categories and Discoverability Score work.
Read the methodologyHow do I improve 3RD's ChatGPT Plugin discoverability?
The levers are the listing surface agents actually read: names, descriptions, keywords, tool metadata, and registry health. Which lever matters depends on where discovery breaks, which is what continuous measurement shows.
What are 3RD alternatives on ChatGPT?
As of 2026-11-02, 3RD competes with 8ight SEO & GEO, Actionbase, AEO/GEO by VibeSEO, Agent Ready, Agent Ready Checker, Agenticaso, AI Interpretation Layer Audit™, AI Product Detective and 95 more in ChatGPT AI Search & LLM Visibility (AEO/GEO), ranked by public Discoverability Score.
Where is this profile measured?
This profile uses the geography attached to the latest public registry snapshot: US. Locale tags are intentionally omitted.