← Back to all apps

Channel99

Businessby Channel99 Inc.
Launched Mar 17, 2026 on ChatGPT

Channel99 real time go to market intelligence connects ChatGPT directly to Channel99’s performance marketing intelligence. giving AI assistants real-time access to unified B2B marketing data and insights.. Powered by Channel99’s advanced attribution, account identification, and AI-driven analytics. The Channel99 connection enables natural-language queries that deliver accurate campaign performance, spend efficiency, audience engagement and cross channel attribution insights eliminating manual data pulls, siloed dashboards and complex API engineering.

Marketers, analysts, and business leaders can ask ChatGPT strategic questions like “Which channels drove the most high-value engagement last quarter?” or “Where should we reallocate budget to improve pipeline efficiency?” and get precise, context-aware results powered by Channel99’s industry leading performance data.

Developed by Channel99 a B2B marketing technology company dedicated to improving ROI, lowering acquisition costs, and bringing financial transparency to digital marketing investments.

6ChatGPT Tools
Channel99 Inc. Developer
BusinessCategory

Available Tools

Build Channel99 app navigation URL

buildAppNavigationUrl
Full Description

Constructs a URL to navigate the user to a specific page in the Channel99 application.

⚠️ PREREQUISITE: You MUST call the listAppRoutes tool first to obtain the available routes and their parameters before constructing any URLs. Do not guess or hallucinate route names or parameter names.

CRITICAL WORKFLOW

  • YOU MUST FOLLOW THIS ORDER:

STEP 1: Identify the route without calling the buildAppNavigationUrl tool. STEP 2: Call the resolveObjectIds tool for ANY parameter that "requires lookup". STEP 3: Wait for the response from the resolveObjectIds tool to return the actual IDs. STEP 4: Call the buildAppNavigationUrl tool using the EXACT IDs returned by the resolveObjectIds tool.

⚠️ EXCLUSION / NEGATION HANDLING:

When the user uses these keywords, you MUST set exclude: true:

  • "NOT in", "not in"
  • "except", "excluding"
  • "other than"
  • "but not", "without"
  • "exclude"

ONLY parameters marked "can be excluded" support the exclude property (string and string[] types only).

EXAMPLES: "companies NOT in Audience A" → w.audienceIds: {value: "<ID>", exclude: true} "all sectors except healthcare" → w.sector.id: {value: "sect_healthcare", exclude: true} "channels other than direct" → w.channelIds: {value: "chnl_direct", exclude: true} "visits NOT equal to 10" → Use range filter instead: w.metrics.visits: {value: "[,9]"} or {value: "[11,]"}

CRITICAL: When you see "NOT" or "except" in the query, CHECK if that parameter "can be excluded" and set exclude: true.

⚠️ COMMON MISTAKES TO AVOID:

1. Calling buildAppNavigationUrl before calling resolveObjectIds Always call resolveObjectIds FIRST, wait for response, THEN call buildAppNavigationUrl

2. Guessing IDs based on patterns (e.g., "audi_nebula_test", "sect_healthcare") Use the EXACT ID returned by resolveObjectIds, which might be complex like "audi:seeddata.upload.audience-1"

3. Using example IDs from documentation Call resolveObjectIds to get the real ID for the user's specific entity

4. Omitting filters when the user mentions filtering criteria Always include searchParams for any filtering criteria mentioned by the user

WHY YOU CAN'T GUESS IDS:

  • IDs can be simple: "sect_healthcare", "chnl_direct"
  • IDs can be complex: "audi:seeddata.upload.audience-1", "inst:customer_abc.prod"
  • IDs can be UUIDs: "550e8400-e29b-41d4-a716-446655440000"
  • Only resolveObjectIds knows the actual format for each entity

Example 1: "Where can I see more information on the 'My Audience 123' audience?" WRONG: pathParams={} CORRECT: pathParams=[{key: "audienceId", value: "<ID_FROM_LOOKUP>"}]

Example 2: "Show me all vendors which belong to the paid search channel?" WRONG: searchParams={} CORRECT: searchParams=[{key: "v.channel.id", value: "<ID_FROM_LOOKUP>"}]

COMPLETE WORKFLOW EXAMPLE:

User Query: "Show me healthcare companies in Europe with more than 10 visits that are NOT enterprise"

Step 1: Call listAppRoutes to get available routes and parameters → Identify the route: webTrafficActivity

Step 2: Identify what needs lookup → "healthcare" needs lookup (type: sector) → "Europe" needs lookup (type: region) → "more than 10 visits" is a range filter (no lookup needed) → "enterprise" needs lookup (type: revrange)

Step 3: Call resolveObjectIds tool: Input: { entities: [ {name: "healthcare", objectType: "sector"}, {name: "Europe", objectType: "region"} {name: "enterprise", objectType: "revrange"} ] }

Response: [ {id: "sect_healthcare", name: "Healthcare", objectType: "sector"}, {id: "regn_europe", name: "Europe", objectType: "region"} {id: "rrng_enterprise", name: "Enterprise", objectType: "revrange"}, ]

Step 4: Call buildAppNavigationUrl tool with the EXACT IDs from Step 3: Input: { route: "webTrafficActivity", searchParams: [ {"key": "w.sector.id", "value": "sect_healthcare"}, ← ID from resolveObjectIds response {"key": "w.region.id", "value": "regn_europe"}, ← ID from resolveObjectIds response {"key": "w.metrics.visits", "value": "[10,]"}, ← No lookup needed {"key": "w.revRange.id", "value": "rrng_enterprise", "exclude": true} ← ID from resolveObjectIds response, exclude: true ] }

Response: "https://app.dev.channel99.com/app/inst/seeddata/web-traffic-activity?w.sector.id=sect_healthcare&w.region.id=regn_europe&w.metrics.visits=[10,]"

Parameters (1 required, 2 optional)
Required
routestring

The route key identifying which page to navigate to. Must be one of the available routes returned by the listAppRoutes tool.

Optional
pathParamsarray

Path parameters as key/value entries (e.g. [{key: "audienceId", value: "<ID_FROM_LOOKUP>"}]). Use resolved IDs from any parameters which require lookup. Type formatting rules: 1. string[]: comma-separated list of values 2. enum: one of the allowed values in the enum field 3. string: a single value 4. number: a valid number value

searchParamsarray

Query string parameters for filtering, sorting, etc. ⚠️ EXCLUSION: If the user says "NOT", "except", "excluding", or "other than", you MUST set exclude: true - Only works for parameters marked "can be excluded" (string and string[] types) - Example: "NOT in Audience A" → [{"key": "w.audienceIds", "value": "<ID_FROM_LOOKUP>", "exclude": true}] - Example: "except healthcare" → [{"key": "w.sector.id", "value": "<ID_FROM_LOOKUP>", "exclude": true}] Use resolved IDs for any parameters which require lookup. Type formatting rules: 1. string[]: comma-separated list of values 2. range: [10,] means >= 10, [,20] means <=20, [10,20] means >= 10 and <= 20. Only square brackets are allowed NOT parentheses. 3. enum: one of the allowed values in the enum field 4. boolean: true or false 5. ruleBased: OR queries are comma-separated, AND queries are separated by + 6. string: a single value 7. number: a valid number value EXCLUDE: Set the exclude property to true to exclude the value instead of including it. Only applicable to string and string[] types which "can be excluded". Examples: - Include: {"key": "w.region.id", "value": "regn_europe" } - Exclude: {"key": "w.region.id", "value": "regn_europe", "exclude": true } Use exclude when the user says "NOT", "except", "excluding", "other than", etc.

Get queryable database schema

getQueryDatabaseSchema
Full Description

Returns the C99 Snowflake database schema.

This tool provides the complete schema information needed to construct SQL queries for the runReadOnlySqlQuery tool. The schema describes all queryable entities including views and user-defined table functions (UDTFs), along with their columns, parameters, and data types.

⚠️ IMPORTANT: The schema you receive from this tool is required in order to call the runReadOnlySqlQuery tool. If you haven't done so already, call this tool so you can query the database to understand the available tables, columns, and their proper usage.

⚠️ UDTF PARAMETERS ARE AUTHORITATIVE:

  • Use the exact parameter names and datatypes from this schema when calling UDTFs with named

arguments.

  • Do not invent parameter names, enum values, or casts that are not shown in the schema.
  • For UDTF parameters with datatype STRING containing JSON array string, pass JSON array text cast

as ::STRING (or NULL::STRING when no filter), never SQL arrays like ARRAY_CONSTRUCT(...) or NULL::ARRAY. Even for a single value, pass a JSON array string (e.g. '["value"]'::STRING).

  • WRONG:

ARRAY_CONSTRUCT('value','value2') NULL::ARRAY

  • RIGHT:

'["value","value2"]'::STRING NULL::STRING

List app routes and accepted parameters

listAppRoutes
Full Description

Returns the available routes and their parameters for the Channel99 web application.

This tool provides the complete route definitions needed to construct URLs using the buildAppNavigationUrl tool. Each route includes:

  • A description of what the route is for
  • Path parameters (required parts of the URL path)
  • Search parameters (optional query string filters)
  • Parameter types, whether they require ID lookup, and whether they can be excluded/negated

⚠️ IMPORTANT: The route definitions you receive from this tool are required in order to call the buildAppNavigationUrl tool. If you haven't done so already, call this tool so you can understand the available routes and their parameters.

Resolve object IDs from Channel99 entity names

resolveObjectIds
Full Description

Resolve known Channel99 entity names to canonical object IDs. Pass only concrete, resolvable entities already extracted from the user request. Do not pass the full user query. Do not call this tool when no resolvable entities are present. Follow these rules for resolution.

Here are the "type" categories:

1. Revenue Range (revrange):

  • Refers to a company's size as measured in total annual revenue.
  • This field is an enum with a fixed set of possible values and is used to determine the market

size of a company. In C99, there are 4 groups of company sizes:

  • 'enterprise' (more than $1B)
  • 'mid-market' (between $100M and $1B)
  • 'small-medium' (between $10M and $100M)
  • 'very small' (less than $10M)
  • If the user mentions a specific revenue value, select the revenue range which most likely

applies. Do not use any other values for revrange other than the 4 listed here. For example, if the user mentions a revenue range such as $200M - $300M, set the "name" to 'mid-market' and the "type" to 'revrange'.

  • If the user mentions a revenue value that spans multiple revenue ranges, select them all

2. Region:

  • Look for any geographic terms (e.g. continent, country, state/province, city) and resolve them

into one of these predefined regions:

  • North America
  • Africa
  • Asia-Pacific
  • Europe
  • Central & South America
  • Middle East
  • Antarctica
  • Example: "accounts in France" → {"name": "Europe", "type": "region"}

3. Industry (Sector):

  • Match mentioned industries to the closest sector name
  • Example: "companies in agriculture" → {"name": "agriculture", "type": "sector"}

4. Channel:

  • Extract channel names (e.g. "direct", "paid search", "paid social", "organic search", "email",

"pr", etc)

5. Named Instances:

  • If the input includes the name of a specific object (e.g., "Pixel A" or "Campaign B"), extract

the name and type.

  • Example: "Show details about Pixel A" → {"name": "Pixel A", "type": "pixel"}

6. Generic Objects:

  • Do not extract names or types for generic object requests (e.g., "list all pixels," "what are

my tags?")

7. TAM (Total Addressable Market):

  • Extract relevant marketing keywords (e.g., sectors, revenue ranges, or regions) mentioned

alongside TAM. Do not attempt to resolve TAM itself as a resolvable entity

  • Example: "Show healthcare companies in my TAM" → [{"name": "healthcare", "type": "sector"}]

8. No resolvable keywords:

  • Do not call this tool if the input does not include resolvable entities.
Examples:
  • Q: "List all campaigns for mid-market agriculture companies"
  • A: [{"name": "mid-market", "type": "revrange"}, {"name": "agriculture", "type": "sector"}]
  • Q: "Details about the Pixel A pixel"
  • A: [{"name": "Pixel A", "type": "pixel"}]
  • Q: "What is the TAM for the healthcare sector"
  • A: [{"name": "healthcare", "type": "sector"}]
  • Q: "Show all companies with annual revenue between $20M and $400M."
  • A: [{"name": "small-medium", "type": "revrange"}, {"name": "mid-market", "type": "revrange"}]
  • Q: "Show all companies in China"
  • A: [{"name": "Asia-Pacific", "type": "region"}]
Parameters (1 required)
Required
entitiesarray

Non-empty array of extracted entities to resolve to IDs. Include only names and types needed for this request.

Execute read-only SQL against the database

runReadOnlySqlQuery
Full Description

Execute a read-only SQL query against the C99 Snowflake database.

⚠️ PREREQUISITE: You MUST call the getQueryDatabaseSchema tool first to obtain the database schema before composing any SQL queries. Do not guess or hallucinate table names, column names, or function signatures.

⚠️ CRITICAL: FULLY QUALIFIED TABLE NAMES REQUIRED ⚠️

  • ALWAYS use fully qualified names: All table and view references in SQL queries MUST use the

fully qualified name format: inst_channel99.c99_ai.table_name. For example, use inst_channel99.c99_ai.ad_keyword instead of just ad_keyword.

  • This applies to ALL table references: JOINs, FROM clauses, and any other table references

MUST use the fully qualified name exactly as shown in the schema from the getQueryDatabaseSchema tool.

  • Example: JOIN inst_channel99.c99_ai.company AS c ON c.company_id = v.company_id

⚠️ CRITICAL LOOKUP USAGE INSTRUCTIONS ⚠️

  • Prefer ID joins over name joins: When possible, join on the ID column of the entity rather

than a name column. Use the resolveObjectIds tool to get the ID if you don't have it. For example, instead of joining on the channel_name column, ask the resolveObjectIds tool for the ID of the channel and join on channel_id instead.

⚠️ CRITICAL UDTF USAGE INSTRUCTIONS ⚠️

  • UDTF Syntax: All UDTFs must be called using the exact format

FROM TABLE(UDTF_NAME(arg1, arg2, ...)) with valid arguments. Never use FROM UDTF_NAME(...) or FROM UDTF_NAME.

  • Casting Requirement: All literal arguments (strings, timestamps, NULLs) must be

explicitly cast using the :: operator. (e.g. '2024-01-01'::TIMESTAMP_NTZ, NULL::STRING, 'campaign'::STRING, etc.).

  • Alias Naming Requirement: Use safe SQL aliases with letters, numbers, and underscores only

(e.g. pipeline_per_dollar). Do not use special characters like $ in unquoted aliases.

  • JOIN Requirement: Always join the UDTF results with dimension tables (like company) to

resolve IDs into human-readable names.

  • ID Requirement: All UDTF parameters that are foreign keys MUST be the ID of the entity

returned by the resolveObjectIds tool. NEVER GUESS THE ID, NEVER ADD A PLACEHOLDER VALUE, and NEVER USE A NAME IN PLACE OF THE ID. Call the resolveObjectIds tool only when you have one or more concrete entities that need ID resolution for the query.

  • Use Columns Returned by the UDTF: Do not invent columns. For example, if the UDTF returns a

column called sum_spend, do not invent a column called spend.

  • Required Parameters: All UDTF parameters that are required MUST be included in the query.
  • Default Value: If a UDTF parameter has a default, use this value in the query if no value

is provided for the parameter. If parameter documentation explicitly says null is allowed for "no filter", follow that parameter documentation. If a default value is provided, let the user know what the default value is.

  • Pay attention to type: For each of the following types, pass the appropriate value:
    • "STRING containing JSON array string": Pass a JSON array formatted string cast as ::STRING

(e.g. '["value1","value2"]'::STRING).

  • "STRING": Pass a string (e.g. 'value'::STRING).
  • "TIMESTAMP_NTZ": Pass a timestamp (e.g. '2024-01-01'::TIMESTAMP_NTZ).
  • grouping_id Note: The grouping_id column contains different IDs based on the

group_by parameter value.

Example:

SELECT v.*, c.company_name
FROM TABLE(inst_channel99.c99_ai.visits(
  '2024-01-01'::TIMESTAMP_NTZ,
  '2024-02-01'::TIMESTAMP_NTZ,
  NULL::STRING,
  NULL::STRING
)) AS v
JOIN inst_channel99.c99_ai.company AS c ON c.company_id = v.company_id

You must use Snowflake SQL syntax or the query will fail to execute.

Format results in a clear, readable way for the user. If there are many rows, consider showing a summary.

Parameters (1 required)
Required
sqlQuerystring

The SQL query based on the database schema from the getQueryDatabaseSchema tool which best answers the user's question. SQL queries you compose should be valid, safe, and performant. You must also adhere to the following conditions: 1. Queries must always be read-only (i.e. only utilize SELECT). 2. Queries must never request more than 100 rows. 3. If the SQL query utilizes a UDTF, all function parameters must always be cast to the appropriate type. For example, if a `NULL` is used by an argument that is a `STRING` then the query should supply `NULL::STRING` as the parameter value. 4. ALL table and view names MUST be fully qualified (e.g., `inst_channel99.c99_ai.table_name`) in every reference including JOINs, FROM clauses, and subqueries. Use the exact names from the schema. If the user's question or SQL query generation process causes any of these rules to be broken, politely decline to make the request. **Additional suggestions:** * Questions related to cost or spend often require `include_spend` to be set to `true` when used in UDTF parameters. * **Date Range Requirements:** The `start_date` and `end_date` parameters of UDTFs are always required and must be determined before composing the SQL query. - **Default Range:** Unless the customer question specifies otherwise, use a 90-day lookback period: `start_date => (CURRENT_DATE() - INTERVAL '90 days')::TIMESTAMP_NTZ` and `end_date => CURRENT_DATE()::TIMESTAMP_NTZ`. - **Minimum Distance:** The `start_date` and `end_date` must never be the same value. They must have a minimum distance of at least one hour. - **Specific Time Periods:** If the customer question specifies a time period (e.g., "last month"), use the `DATE_TRUNC()` function to calculate the appropriate range. For example, to express "last month": `start_date => DATE_TRUNC('month', CURRENT_DATE() - INTERVAL '1 month')::TIMESTAMP_NTZ`, `end_date => DATE_TRUNC('month', CURRENT_DATE())::TIMESTAMP_NTZ` - **WHERE Clause Dates:** When filtering on date columns (e.g., `visit_date`, `created_at`), use the same `start_date` and `end_date` values established for the UDTF parameters. - Always state which dates you used in the response. * SQL queries should be composed in such a way so that object names are present as a column in the response, instead of only the ID. Make joins to the appropriate table to ensure that both object IDs and names are present.

Search support documentation

searchSupportDocs
Full Description

Search Channel99 support documentation for answers to product questions, feature explanations, troubleshooting steps, best practices, and product release notes. If a URL is referenced in the article content, include it in the response.

Parameters (1 required)
Required
querystring

Short search query for support docs. Pass only the product question, not full chat history.