All documentation

Visibility

Attributes

A weekly study that asks each chat engine on your plan, and ChatGPT (app), what your brand and each active tracked competitor are best known for, then which brands it names for each chosen quality, and shows each brand's association and market prominence side by side, with the quotes behind them and what changed since the last comparable study.

Attributes for the Quillstone demo project: the Story continuity tracking row with its association score, its market prominence and the leader, opened to the engines' quotes and the market ranking of every brand named

The screenshot shows the Quillstone demo project on development data.

What this screen shows

Open Attributes from the Attributes tab under Brand perception in the sidebar. It answers two questions about your brand and each active tracked competitor, from a separate attribute study, asked of the chat engines on your plan and ChatGPT (app), rather than from your tracked prompts:

  • What is the brand known for? The qualities AI engines associate with the brand when asked about it directly, such as "Ease of use" or "Pricing transparency", each with an association score and how many engines named it.
  • Who is known for each quality? For the attributes the study asked about, which brands engines name when asked who is best known for that quality, with the selected brand's market prominence, its position among the brands named, and the leader, which can be a brand you do not track.

The two are shown side by side because they can disagree: every engine can describe a brand as fast and still name another brand first when asked who is known for speed. For each attribute the screen also shows what changed since the previous comparable study, and each row opens to the quotes behind it (api/services/attributes/read.py#attributes_view, api/schemas/attributes.py#AttributeRow, #MarketOut).

The two questions each engine is asked

A study has two phases, each with its own fixed question.

Phase 1, known for. For each brand, every engine is sent this question, with the brand's name and domain filled in (api/services/attributes/question.py#build_association_question):

What is {name} ({domain}) best known for among {market}? List the
qualities and characteristics people most associate with {name}, good or
bad, from most to least prominent, one per line, and cite sources where
you can.

The " among {market}" part is included only when the study has a market (see Your market); your market is used for the competitors too. Name, domain and market are trimmed to 120, 255 and 120 characters (api/services/attributes/question.py#MARKET_LIMIT).

Phase 2, the market. For each attribute chosen for the market question (see Which attributes are asked about the market), every engine is sent this question (api/services/attributes/question.py#build_market_question):

Among {market}, which brands are best known for {attribute}? Name the
brands most associated with {attribute}, from most to least, one per line,
and cite sources where you can.

The attribute is its label trimmed to 80 characters, with only its first letter lower-cased, and only when the second letter is lower case: "Ease of use" is asked as "ease of use", while "AI coding" and "GDPR compliance" keep their capitals (api/services/attributes/question.py#_attribute_in_sentence). The market is trimmed to 120. Your brand is not named in this question, so the engine is not steered toward it. The market is fixed on the study when the study is created and used for every question of that study, and each question is stored when it is created, so editing your market or project during a study changes nothing already asked (api/services/attributes/studies.py#create_study, api/services/attributes/pipeline.py#start_ranking, #run_answer).

Both questions are written in English. When your project has a default language (see Languages and templates), the study is created in that language, and each engine also receives the same plain-language instruction to answer in that language that a tracked prompt in that language receives, for both phases. ChatGPT (app) gets it added after the question, because a language setting alone does not change the language it answers in (see What reaches ChatGPT). With As written, nothing is added (api/services/brand_study/question.py#question_search_context, #study_prompt). No city or persona is sent, and no country except to ChatGPT (app), which is always asked with the United States as its country (api/services/brand_study/question.py#STUDY_APP_COUNTRY).

Each question carries a version number (api/services/attributes/question.py#ASSOCIATION_QUESTION_VERSION, #MARKET_QUESTION_VERSION). Studies are only compared with studies that asked the same versions of both questions in the same language about the same market.

Which brands and engines

Phase 1 asks about your brand, by your project's name and domain, and then each active tracked competitor, by its name and domain, in the order the competitors were added, up to your plan's competitor allowance. A competitor saved without a name is asked about by its domain. Paused competitors are not asked about, and sub-brands are not asked about separately (api/services/brand_study/engines.py#study_subjects).

Every brand is asked of every engine your plan includes that is active and currently available when the study is created, except Google AI Overviews, Google AI Mode and Gemini (app), three of the four engines collected through DataForSEO, which receive only the question as written, with no instruction to answer in the study's language. ChatGPT (app), the fourth, is asked, with the language instruction added to its question as described above (api/services/brand_study/engines.py#study_engines_for_plan, #STUDY_EXCLUDED_PROVIDERS, api/services/attributes/studies.py#create_study; see Engines and measurement). Each (brand, engine) pair is one answer. Each answer keeps the brand's name and domain as they were when the study was created (api/models/attribute.py#AttributeAnswer).

Phase 2 sends each chosen attribute to the same engines phase 1 asked, whether or not they answered there; each (attribute, engine) pair is one answer (api/services/attributes/pipeline.py#_association_scores, #start_ranking).

When studies run

Studies run automatically once a week, with no setting to turn on. A systemd timer (discoveredby-cli@enqueue-attribute-studies.timer) runs every Thursday at 05:00 UTC and starts a study for every active project whose owner's account is active and whose owner's plan includes Attributes, unless the project already has a study running or one was created in the last 6 days (api/cli.py#cmd_enqueue_attribute_studies, api/services/attributes/studies.py#enqueue_scheduled_studies, #SCHEDULE_INTERVAL). A project whose plan has no available engines is skipped.

Owners and editors can also press Run now. It is refused while a study is already running, and for 24 hours after the latest study that counts was created (api/services/attributes/studies.py#start_manual_study, #RUN_COOLDOWN). Viewers cannot run a study (api/routers/attributes.py#start_study). A study that never ran because it could not be queued, or that was interrupted on our side, does not count toward the 24 hours or the 6 days; a study that ran and failed does count (api/services/attributes/studies.py#UNCOUNTED_ERROR_KINDS).

A study collects the phase 1 answers, groups the attributes, asks the market questions, then succeeds. The screen shows the latest succeeded study and a history of the 10 most recent studies, each marked weekly or on demand, with its status; you can open any earlier succeeded study from that list (api/services/attributes/read.py#HISTORY_LIMIT, #_selected_study).

From answer to attributes

Each engine's answer is saved, cut to 50,000 characters, with the model the engine reported (its default model when it reports none) and the sources it cited, exactly as for Objections (api/services/attributes/pipeline.py#run_answer, #RESPONSE_TEXT_LIMIT, api/services/brand_study/sources.py#model_of, #capture_sources).

Another AI model then reads the first 16,000 characters of a phase 1 answer and lists the qualities it associates with the brand, in the order they appear, as short neutral phrases such as "Ease of use" rather than "Acme is easy to use", each with the sentence from the answer that states it. It is told to leave out qualities of other brands, plain facts that name no quality, such as the founding year, and statements about how much is known or published about the brand or how visible it is, such as "few reviews" or "low visibility", the answer's own uncertainty and conclusions drawn from missing information, since those describe what the engine knows rather than the brand. It is also told to treat the answer as data, not instructions (api/services/attributes/extraction.py#build_association_prompt, #EXTRACT_TEXT_LIMIT). A brand whose one distinction really is being little known is therefore not measured for it.

Our code then decides what is kept, with the same rules as objections (api/services/attributes/extraction.py#validate_association, api/services/brand_study/ranking.py#locate_and_rank):

  • At most 10 attributes are read from one answer, and a phrase is cut to 80 characters (api/services/brand_study/ranking.py#MAX_ITEMS_PER_ANSWER, api/services/attributes/extraction.py#ATTRIBUTE_LIMIT).
  • The quote must be found in the saved answer, exactly or ignoring case (api/services/brand_mentions.py#_locate). The stored quote is the answer's own text, cut to 300 characters; one shorter than 20 characters is dropped as a heading or label, and when two quotes overlap only the one the model listed first is kept (api/services/brand_study/ranking.py#QUOTE_LIMIT, #MIN_QUOTE_LENGTH).
  • Rank is the order of the quotes in the answer, and the score is 100 for rank one, minus 10 for each rank after it (api/services/brand_study/ranking.py#score_for_rank).

An answer with at least one kept attribute has succeeded; one with none, including an empty answer or an engine that declined, answered with no attributes. A failed extraction call marks the answer failed (api/services/attributes/pipeline.py#_extract).

How attributes are grouped

When every phase 1 answer is in, AI model calls assign each extracted phrase to an attribute group, in batches of at most 120 phrases, each batch saved before the next starts (api/services/attributes/pipeline.py#group_study, #GROUP_BATCH_SIZE). Each call is sent the phrases without the brand they were about, so the same quality said of different brands can share a group. It is also sent all of your attributes first, marked as yours, then the 150 most recently seen other groups of the project (api/services/attributes/pipeline.py#GROUPS_IN_PROMPT). The model is told to reuse a group only when it names the same quality, to hold your attributes to the same test as any other group rather than prefer them, and otherwise to create a new group with a label written without brand names (api/services/attributes/grouping.py#build_grouping_prompt). A label is cut to 80 characters (api/services/brand_study/grouping.py#LABEL_LIMIT).

Our code checks each batch before saving it: every phrase must be assigned exactly once, to a group of this project that was sent or to a new group the model defined (api/services/brand_study/grouping.py#validate_grouping). If the output fails that check the model is asked once more with the problems; if that fails too, or a call fails, the study fails. A new group whose label matches an existing group's label, ignoring case, is merged into it, including one of your attributes added while the batch was being grouped (api/services/attributes/pipeline.py#_apply_plan).

Groups belong to the project and are shared by every brand and every later study, which is what makes comparing brands and studies possible. The grouping and the labels are an AI model's judgement and wording: two similar qualities can land in separate groups, or a group can be broader than you would draw it. The quotes under each attribute are the check on that.

Your market

The market is a short phrase for what your project is and who it is for, such as "book-writing software for authors", which both questions name. Owners and editors set it under Your market on the Attributes screen: at most 120 characters on one line, with runs of spaces made one, and an empty value removes it (api/services/attributes/market.py#clean_market, #MARKET_LIMIT, #set_market, api/routers/attributes.py#set_market). A market that names your brand or a tracked competitor, by any of its names, is refused with "Leave brand names out of the market." (api/services/attributes/market.py#MARKET_NAMES_A_BRAND). Setting it is recorded in the project's activity (api/services/attributes/market.py#set_market). Viewers can see it but not change it.

The market is not your project's business type, which is one of a short list of categories such as SaaS; neither question uses the business type. Each study keeps the market it was created with and shows it as "Market asked", so a change applies from the next study (api/models/attribute.py#AttributeStudy, api/schemas/attributes.py#StudyDetail).

Your site research also suggests a market: the product category a buyer would compare you within, in a few words and without brand names (api/services/research.py#business_profile_schema, #business_profile_prompt). The suggestion is kept only when it passes the same rules as a typed market, brand names included; otherwise it is dropped (api/services/attributes/market.py#clean_suggested_market). The newest kept suggestion is the one used (api/services/attributes/market.py#latest_market_suggestion). While your market is empty, the Attributes screen fills the market box with it, labelled as suggested from your site research, and saving it works as for a typed market (api/services/attributes/read.py#attributes_view, frontend/src/routes/(app)/sentiment/attributes/+page.svelte#suggestedMarket). A study that starts while your market is empty saves the suggestion as your market and asks it, if it still leaves out every brand you track, and the project's activity records it with no user (api/services/attributes/studies.py#create_study, api/services/attributes/market.py#adopt_market_suggestion). It is then your market like any other, and owners and editors can change it. With no suggestion, studies skip the market question until someone sets one. A project gets its first suggestion from its next research run.

The wording decides what market prominence means. A broad market such as "software" puts your brand among every well-known software brand, where a small brand is rarely named.

Your attributes

Owners and editors can add up to 10 attributes the project wants to be known for, each a label of 1 to 80 characters on one line, with an optional description of up to 240 characters (api/services/attributes/custom.py#add_custom, #MAX_CUSTOM_ATTRIBUTES, #LABEL_LIMIT, #DESCRIPTION_LIMIT). A label that names your brand or a tracked competitor, by any of its names, is refused with "Leave brand names out of the attribute." (api/services/attributes/custom.py#NAMES_A_BRAND). Adding a label that matches an existing attribute group, ignoring case, makes that group one of yours, keeping its history.

Removing one of your attributes only takes the mark off: the group and its history stay as an ordinary attribute (api/services/attributes/custom.py#remove_custom). Adding and removing are recorded in the project's activity (api/services/attributes/custom.py#_audit). A change applies the next time a study groups its attributes and chooses what to ask, which includes a study still collecting answers when you make it (api/services/attributes/pipeline.py#group_study, #start_ranking). Viewers can see your attributes but not change them (api/routers/attributes.py#add_custom_attribute, #remove_custom_attribute).

Your attributes are offered to the grouping model first, and the engines' wording is grouped into them when it names the same quality, by the same test as any other group; they are always asked in the market question (see the next section). Each of them is listed on the screen even when no engine associated it with the selected brand (api/services/attributes/read.py#attributes_view).

Which attributes are asked about the market

When grouping finishes, our code chooses the attributes for phase 2, in this order (api/services/attributes/selection.py#select_market_attributes):

  1. Every one of your attributes, in the order their attribute groups were created (at most 10).
  2. Up to 4 of your own brand's strongest other attributes in this study, highest association first (#OWN_TOP_ATTRIBUTES).
  3. The strongest remaining attributes of any brand in the study, by the highest association any brand has, until 8 attributes beyond yours are chosen (#DISCOVERED_MARKET_ATTRIBUTES).

So a study asks about at most 18 attributes. Step 3 is what brings in a quality only a competitor is known for. Ties go to the label in alphabetical order, and an attribute no brand was associated with is only asked when it is one of yours.

Before choosing, any attribute whose label names your brand or a tracked competitor as a whole word is left out, whether a model or a person wrote it, so no brand name reaches the market question. This can happen to one of your attributes too, for example when a competitor with that name is added later (api/services/attributes/pipeline.py#start_ranking, api/services/attributes/brands.py#names_tracked_brand). A name that is only a brand's domain alias, such as "close" from close.com, does not count here or in your attribute labels, since it is also an ordinary word (api/services/attributes/brands.py#_domain_only_names); in your market it does count (api/services/attributes/market.py#set_market). The chosen attributes and their labels are stored on the study, so renaming or merging a group later never changes what a study asked (api/models/attribute.py#AttributeStudy).

Phase 2 needs a market, because the market question names one. If the study was created without one, or no attribute is chosen, phase 2 is skipped: the study succeeds with its phase 1 results and records why, which the screen shows, with a link for owners and editors to set the market (api/services/attributes/pipeline.py#_skip_market, api/schemas/attributes.py#StudyDetail).

From answer to market ranking

An AI model reads the first 16,000 characters of each market answer and lists the brands it names as associated with the attribute, in the order they appear, each with the line or sentence that names it. It is told to leave out brands mentioned only as not having the quality (api/services/attributes/extraction.py#build_ranking_prompt). Our code then decides what is kept (api/services/attributes/extraction.py#validate_ranking):

  • At most 10 brands are read from one answer, and a name is cut to 120 characters after quote marks, emphasis marks and a pair of brackets around it are removed (api/services/attributes/extraction.py#BRAND_NAME_LIMIT).
  • The quote must be found in the saved answer; a short line such as "Asana" is a valid quote.
  • The name must appear inside the quote as a whole word, ignoring case, or the brand is dropped: "Box" is never read out of "Dropbox".
  • Rank is the order of the names in the answer, scored 100 for rank one minus 10 for each rank after it. The name stored is the answer's own spelling at that position.
  • When two names overlap in the answer, such as "Acme Cloud" and "Acme" at the same place, only one is kept: the earlier, and at the same position the longer. A brand named twice in one answer keeps its first naming.

Which brand a name is, is decided by our code, never by the model (api/services/attributes/brands.py#load_matcher, #match, api/services/brand_families.py#family_roots):

  • A name counts as your brand or a tracked competitor when one of that brand's names occurs in it as a whole word, ignoring case. A brand's names are its display name, its aliases, and its active sub-brands' names and aliases, so a sub-brand counts as its family, and "Acme Cloud" counts as Acme when Acme is tracked.
  • When names of several brands match, the longest matching name wins. If the longest match belongs to two brands, the name is left untracked rather than guessed.
  • Any other name is an untracked brand. Names that are the same apart from case, spacing and trailing punctuation count as one brand (api/services/attributes/brands.py#normalize_brand), shown with the spelling seen most often in the study (api/services/attributes/read.py#_spellings).
  • Spelling variants of untracked brands are merged when the screen is read (api/services/attributes/brands.py#merge_variants). A name whose words begin with every word of a shorter name named in the same study counts as that shorter name: "Reedsy Studio" counts as "Reedsy" when "Reedsy" is named too. When several shorter names fit, as "Reedsy" and "Reedsy Studio" both fit "Reedsy Studio Pro", the shortest wins. One trailing bracket is ignored first, so "Canvas (Instructure)" counts as "Canvas" (api/services/attributes/brands.py#canonical_brand). Your brand and tracked competitors are never merged this way; they are already matched by their names.
  • A merged brand's score from an engine is its best score among the spellings in that engine's answer, and each engine counts once in Named by (api/services/attributes/read.py#_merged, api/services/brand_study/metrics.py#prominence, #raised_by). It is shown under the shortest name's most frequent spelling without a trailing bracket, so "Google (Google Workspace for Education)" is shown as "Google" (api/services/attributes/read.py#_Brands). For an untracked brand, the market ranking lists the other spellings engines used for it in that attribute as "also named as", leaving out spellings that differ only in case, spacing or trailing punctuation (api/services/attributes/read.py#ranking_view, api/schemas/attributes.py#RankedBrandOut). Positions, the leader and change all count the merged brand once.
  • The merge has limits. A company and its product merge when both are named: "Google Docs" counts as "Google" in a study where "Google" is named. Different brands that share a first word do not merge unless the shorter name is itself named, so "Proton Mail" and "Proton Drive" stay two brands until an engine names "Proton". Nothing is merged in storage: each naming keeps the name as the engine wrote it.
  • A paused competitor is not matched, so its name is untracked. The match is stored when the answer is read, so adding an alias later does not change earlier studies.
  • Your brands and their names are read again for each market answer (api/services/attributes/pipeline.py#_extract). Pausing or adding a competitor, a sub-brand or an alias during the few minutes a study asks the market questions can therefore key one brand two ways within that study, which splits its prominence.

How sources are linked

Our code links sources to each attribute quote and each brand quote the same way as for objections: a source is linked when the engine placed its citation on the quote or in the run of citation markers directly after it (api/services/brand_study/sources.py#link_sources). Perplexity and Grok (for its inline citations) record where they cite, so their sources can be linked. ChatGPT (app) records where each source's link first appears in the stored answer; the app usually, though not always, writes that link right after the text it supports, and a source whose link is not found in the stored answer links nothing. Gemini (API)'s positions are counted in bytes, so they are usually close for English but land in the wrong place for languages written in another script. Claude records no position, so its answers show no sources (api/services/llm.py#_chatgpt_app_answer, #_sonar_marker_citations, #run_grok, #run_gemini, #run_anthropic). The details, and their limits, are in how sources are linked. A linked source shows where the engine placed its citation; it is not a check that the page says what the quote says.

What the numbers mean

Association, for the brand selected, over the engines that answered its phase 1 question (with attributes or with none; an engine whose answer failed is left out) (api/services/brand_study/metrics.py#prominence, #raised_by):

  • An engine's score for an attribute is its highest score among the phrases grouped into that attribute, and 0 if it answered without it.
  • Association is the average of those scores over the answered engines, from 0 to 100, rounded to one decimal. With three engines answering, one listing the attribute first (100), one third (80) and one not at all (0), association is 180 ÷ 3 = 60.0.
  • Associated by is how many of the answered engines named it.

Market prominence, for an attribute asked in phase 2, over the engines that answered that attribute's market question (api/services/attributes/read.py#_market_row, #ranking_view):

  • A brand's market prominence is the same average of its scores in those answers, 0 for an engine that answered without naming it.
  • Named by is how many of those engines named the brand.
  • Position is 1 plus the number of brands named for that attribute with a higher market prominence, so "#3 of 7 named" means two brands are ahead. Brands with the same market prominence share a position: two brands tied first are followed by a brand in third (api/services/attributes/read.py#_positions). A brand no engine named has no position.
  • The leader is the brand with the highest market prominence, tracked or not. Ties go to your brand, then to competitors in the order they were added, then to untracked brands by name (api/services/attributes/read.py#_Brands); when another brand has the same market prominence the screen marks the leader as tied (api/schemas/attributes.py#LeaderOut).

A row opens to its evidence: for each engine, the rank, the phrase, the quote from the answer and its sources, and, for an attribute asked in phase 2, the full market ranking of every brand named, with each engine's rank, the name as written, the quote and its sources (api/schemas/attributes.py#EvidenceOut, #RankedBrandOut, #RankingEvidenceOut). Above the table, each engine asked about the selected brand is listed with its model and whether it answered, answered with no attributes, or failed, with the kind of failure but never the engine's raw error text (api/schemas/attributes.py#EngineStatus).

If no engine answered for a brand, or no engine answered an attribute's market question, that number is unavailable rather than 0. An attribute the study did not ask about the market has no market figures at all.

The two scores are not comparable with each other. Association comes from a question about one brand, where the engine lists that brand's qualities; market prominence comes from a question about the whole market, where every brand named competes for the same ranks. A high association with a low market prominence means engines describe the brand that way but name other brands first for it; the reverse means engines name the brand for a quality they do not reach for when describing it. Compare each score across brands and across studies, not with the other score.

What changed since the previous study

A study is compared with the most recent earlier succeeded study of the project that asked the same versions of both questions in the same language about the same market, where no market matches only no market (api/services/attributes/read.py#_previous_study).

Association change is computed only over the compared engines: those that answered for the selected brand in both studies. Market prominence change is computed only for an attribute asked in both studies, over the engines that answered that attribute in both. Both studies' figures are recalculated over those engines alone and the change shown is the difference in points, so an engine joining or leaving your plan, failing in one week, or an attribute asked in only one of the two studies does not make anything look new or gone (api/services/attributes/read.py#_market_common, #_change).

Two changes to your own setup are not compared either:

  • A competitor the earlier study did not ask about reads No comparison for market prominence, not New. If it was added since, the earlier study stored its namings under its plain name, as an untracked brand; if it was beyond your plan's competitor allowance then, its namings were already matched to it, but it was not one of the brands that study asked about (api/services/attributes/read.py#_market_change, api/services/brand_study/engines.py#study_subjects).
  • One of your attributes that became yours after the earlier study was created reads No comparison for association, since grouping from then on can put wording into it that went to another attribute before (api/services/attributes/read.py#attributes_view, api/models/attribute.py#AttributeGroup).

What the comparison still cannot tell apart: a name or alias added to a brand that was already asked about can make that brand read as rising or new once, because its namings under the new name were untracked in the earlier study; pausing or deleting a competitor between studies makes its name an untracked brand from then on, since only active competitors are matched, so in the market ranking it can read as New under its plain name (api/services/attributes/brands.py#load_matcher, api/services/attributes/read.py#_market_change).

For market change, spelling variants are merged over the names of both studies together (api/services/attributes/read.py#_previous_market), so a brand named "Reedsy Studio" last time and "Reedsy" this time is compared as one brand, rising, falling or steady, rather than read as new in one study and gone from the other. When the earlier study named a shorter name that two brands of this study both begin with, such as "Proton" then and "Proton Mail" and "Proton Drive" now, both read No comparison, since the earlier figure cannot be split between them (api/services/attributes/read.py#_market_change).

The change statuses use the same 15-point threshold as objections (api/services/brand_study/metrics.py#change_status, #CHANGE_THRESHOLD):

  • New: the compared engines did not name it last time and do now.
  • Rising or Falling: it moved by 15 points or more, up or down, over the compared engines.
  • Steady: it moved by less than 15 points.
  • Gone: the compared engines named it last time, and no engine that answered this time names it.
  • No comparison: there is no earlier comparable study, no engine answered in both, no compared engine named it in either study, (for market prominence) the attribute was not asked in both or the brand was not asked about in the earlier study, or (for association) the attribute became one of yours since.

Something a compared engine named last time, and that only an engine not being compared names this time, reads as falling or steady over the compared engines, not as gone.

An attribute that is gone from the selected brand's association moves out of the table to a separate list of attributes no longer associated, with its earlier association over the compared engines. One of your attributes, or one asked in the market question, stays in the table instead, marked Gone (api/services/attributes/read.py#attributes_view).

When a study or an answer fails

One failed answer does not fail the study. A study fails when every phase 1 answer failed, when grouping fails, when it could not be queued, or when it is still collecting, grouping or asking the market questions with no progress for 90 minutes (api/services/attributes/pipeline.py#finalize_association, api/services/attributes/studies.py#expire_interrupted, api/services/brand_study/engines.py#INTERRUPTED_AFTER). Market answers never fail the study: when the last one is in, however many failed, the study succeeds (api/services/attributes/pipeline.py#finalize_market).

A failed study's results are not shown, including one interrupted while asking the market questions. When the newest study failed, the screen keeps showing the last succeeded one and notes the failure (api/services/attributes/read.py#attributes_view).

Access

Any current project member can read this screen, viewers included. It is available when the project owner's plan includes Attributes: standard Starter, Growth and Pro presets do, Free and Trial do not (api/services/entitlements.py#standard_entitlements, api/routers/attributes.py#read_attributes). Without it the screen shows an upgrade message, no studies run, and your attributes cannot be changed. Stored studies are kept and become readable again if the plan returns. Only owners and editors can press Run now, set the market or change your attributes (api/services/attributes/read.py#RUNNERS, api/routers/attributes.py#set_market).

Export, API and MCP

The same results are available as the attributes file export, through the customer API's GET /attributes route with the attributes:read permission, and through the list_attributes MCP tool, each also gated by the Attributes entitlement (api/services/exports/attributes.py#COLUMNS, api/services/customer_api.py#attributes_page, api/services/customer_mcp.py#list_attributes). Their rows come in two measures: association, one row per attribute phrase in each phase 1 answer, and market, one row per brand named in each market answer, each with its rank, score, attribute, quote and source URLs, from succeeded studies only. Market rows give each brand as the engine wrote it (api/services/exports/attributes.py#market_statement); spelling variants are merged only on the screen. See Exports and activity, Customer API and keys and MCP connector.

How this differs from Brand reasons and Objections

Brand reasons counts the reasons your tracked prompts' answers give for or against each brand, and Objections asks engines directly for each brand's downsides. Both measure why engines favour or caution against a brand. Attributes measures something else: what engines say a brand is known for, good or bad, and which brands they name for a quality. An attribute has no positive or negative side; "Expensive" is an attribute like any other.

Study answers are kept apart from your tracked prompts' answers (api/models/attribute.py#AttributeAnswer). They use no prompt slot and change no visibility metric, sentiment figure, Brand reasons count, Explorer result or alert.

What this does not include

  • No alerts or emails when an attribute appears or moves.
  • No editing, merging, renaming or hiding of attribute groups the model created; only your attributes can be managed.
  • No location: studies are not run per country or city (ChatGPT (app) is always asked with the United States as its country), and no persona is used.
  • No separate study of a sub-brand; its names count toward its family.
  • No suggested market: the market is what an owner or editor types, and nothing fills it in or derives it from your business type.
  • No re-running of a stored study, no backfill of weeks before the feature, and no deleting of studies from the app.

Last verified 2026-09-29

Start monitoring your AI visibility.

See how AI search engines talk about your brand.

Free to start. No credit card required.