Pré-visualizar
Executa um audience criteria contra o BigQuery e retorna uma amostra de linhas reais mais o total, a partir do corpo (ainda não persistido) ou por id de um critério salvo.
Pré-visualizar
Executa um audience criteria contra o BigQuery (limitado por limit) e
retorna uma amostra das linhas reais correspondentes mais o total do universo. Um
único motor atende dois pontos de entrada:
POST /api/audience-criterias/preview-from-body— executa uma definição enviada no corpo (ainda não persistida).POST /api/audience-criterias/:id/preview— executa um critério já salvo, referenciado por seuid.
Ambos retornam a mesma forma de resposta:
IPreviewAudienceCriteriaResult.
Diferente de Gerar SQL, preview não retorna SQL; e diferente de Validar (que só faz um dry-run), preview traz dados de verdade: executa a consulta e mostra linhas.
Dentro de um projeto, toda audiência que não seja a audiência raiz é executada intersectada com a audiência raiz do projeto — veja Interseção com a audiência raiz.
Auth: Obrigatória — permissão audience-criteria:view-sql (ambos os endpoints).
Preview consome cômputo do BigQuery em cada chamada (executa a audiência de
verdade, não um dry-run). Para limitar o custo, cada consulta roda com
maximumBytesBilled de 10 GB (10737418240 bytes) e um timeout de 30 s
(jobTimeoutMs): uma consulta que exceda qualquer um dos dois limites é
rejeitada com 400 em vez de ser cobrada. Use um limit pequeno enquanto
você itera.
O SQL que é executado aponta para o BigQuery: referencia as tabelas como
`<gcp-project>.<dataset>.<table>`, onde o <gcp-project> (o projeto do Google
Cloud, não um projeto da Reten) vem da configuração de ambiente da API e o <dataset> é resolvido a partir do tenant. Nenhum dos
dois faz parte do contrato de entrada.
POST /api/audience-criterias/preview-from-body
Executa uma definição enviada no corpo, sem persisti-la.
Auth: Obrigatória — permissão audience-criteria:view-sql
O endpoint responde 201 Created —não 200—, mesmo que não crie nenhum
recurso.
Corpo da requisição
Nível raiz (PreviewFromBodyDto): a definição do critério (CriteriaDefinitionDto)
mais o campo limit.
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
queryBlocks | QueryBlockDto[] | Sim | No mínimo 1 elemento. Cada bloco ≈ um statement SQL completo. |
composedWith | CreateCompositionDto[] | Não | Compõe esta definição com outras audiências via operações de conjunto. |
limit | number (integer) | Não | Tamanho da amostra de rows. Inteiro 1..500. Padrão 100 (veja limit). |
criteriaId | string (UUID) | null | Não | A audiência salva que esta definição edita: o rascunho assume a identidade dessa audiência, então gera o mesmo resultado que essa audiência gerará ao ser salva (veja Interseção com a audiência raiz). Ausente ou null: uma audiência nova. Deve ser um UUID válido (caso contrário, 400) de uma audiência do projeto ativo (caso contrário, 404). |
Diferente de Criar, a definição
não leva name nem description: é apenas a árvore de consulta mais limit. A
validação é estrita, então enviar name/description (ou qualquer outra
propriedade desconhecida) produz um 400.
Definição do critério
É a mesma árvore que Criar recebe, sem os
campos name/description. Está documentada aqui de forma autocontida.
queryBlocks[] — bloco de consulta
Cada elemento de queryBlocks (QueryBlockDto) é um statement SQL completo:
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
order | number (integer) | Sim | Posição do bloco; inteiro ≥ 0. |
setOperator | SetOperatorEnum | Não | Combina este bloco com o anterior. Ausente no primeiro bloco; obrigatório nos demais (veja regras). |
from | FromDto | Sim | Fonte de dados: tabela principal + joins. |
select | SelectDto | Sim | Projeção (colunas e/ou agregações). |
timeWindow | TimeWindowDto | Não | Janela temporal do bloco (união discriminada por timeOperator). |
where | WhereDto | Sim | Árvore de predicados. Obrigatório mesmo que seja um grupo vazio. |
groupBy | ColumnRefDto[] | Não | Colunas de agrupamento. |
having | HavingDto | Não | Filtro sobre agregados. |
O setOperator de um query block combina blocos dentro da mesma definição;
não deve ser confundido com o setOperator de uma composição,
que combina critérios inteiros. São dois níveis distintos de operação de conjunto.
ColumnRefDto — referência de coluna
Usado em toda a árvore (select, filtros, group by, joins, agregados, janela temporal):
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
table | string | Sim | Tabela do catálogo. Não vazio. |
column | string | Sim | Coluna. Não vazio. Pode ser um caminho STRUCT (ex.: "pricing.final_amount"). |
Toda coluna é sempre qualificada com sua table para evitar ambiguidade.
from — fonte de dados (FromDto)
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
table | string | Sim | Tabela principal do catálogo. Não vazio. |
joins | JoinDto[] | Não | Joins com outras tabelas. Padrão []. |
unnests | ColumnRefDto[] | Não | Colunas repetidas declaradas como fonte de linhas (uma linha por elemento). Uma audiência não as aceita: omita o campo ou envie [] (o padrão); uma lista não vazia retorna 400. |
Cada JoinDto:
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
type | JoinTypeEnum | Sim | INNER | LEFT | RIGHT | FULL. |
table | string | Sim | Tabela a unir (do catálogo). Não vazio. |
on | JoinPredicateDto[] | Sim | Condições de join. |
Cada JoinPredicateDto é um par de colunas: { left: ColumnRefDto, right: ColumnRefDto }.
select — projeção (SelectDto)
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
distinct | boolean | Sim | Aplica SELECT DISTINCT. |
items | (SelectColumnItem | SelectAggregateItem)[] | Sim | Não vazio. União discriminada pelo campo kind. |
Os items são discriminados por kind:
-
Coluna —
kind: "column":Campo Tipo Obrigatório Descrição kind"column"Sim Discriminador. columnColumnRefDtoSim Coluna projetada. aliasstring Não Deve corresponder a ^[A-Za-z_][A-Za-z0-9_]*$. -
Agregado —
kind: "aggregate":Campo Tipo Obrigatório Descrição kind"aggregate"Sim Discriminador. aggregateAggregateDtoSim Expressão de agregação. aliasstring Sim Aqui o alias é obrigatório. Mesmo regex de identificador.
AggregateDto:
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
aggregationOperator | AggregationOperatorEnum | Sim | COUNT | SUM | AVG | MIN | MAX. |
operand | object | Sim | O que é agregado. União discriminada por kind: column, star ou arithmetic (veja abaixo). |
distinct | boolean | Não | Aplica DISTINCT dentro do agregado. |
operand —o que é agregado— é discriminado por kind:
kind | Campos adicionais | Significado |
|---|---|---|
column | column: ColumnRefDto | Uma coluna do catálogo. |
star | (nenhum) | *: conta linhas. Só é válido com COUNT e sem distinct (COUNT(DISTINCT *) não é permitido). |
arithmetic | arithmeticOperator: ArithmeticOperatorEnum, left, right | Expressão binária. Cada lado é outro operando: uma column ou um arithmetic aninhado (nunca star). |
ArithmeticOperatorEnum: ADD | SUBTRACT | MULTIPLY | SAFE_DIVIDE (uma divisão que retorna
NULL quando o denominador é zero, em vez de fazer a consulta falhar). As colunas de uma expressão
aritmética precisam ser numéricas (INT64, NUMERIC, BIGNUMERIC, FLOAT64), e as expressões se
aninham até 3 níveis de arithmetic, contando o externo.
where — árvore de predicados (WhereDto)
O where é uma árvore recursiva. O nó raiz é sempre um grupo, e suas folhas são de
dois tipos:
kind | O que filtra |
|---|---|
group | Não é uma folha: agrupa filhos com AND / OR. Os grupos podem ser aninhados. |
predicate | Uma coluna escalar de uma tabela do from. |
recordPredicate | Uma coluna RECORD REPEATED: pelo menos 1 elemento satisfaz o sub-filtro. |
Grupo — kind: "group"
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
kind | "group" | Sim | Discriminador. |
logicalOperator | LogicalOperatorEnum (AND | OR) | Sim | Conectivo entre os filhos. |
children | (Group | Leaf)[] | Sim | Filhos do grupo; podem ser grupos aninhados. |
logicalOperator é sempre obrigatório em um grupo, mas só tem efeito com
2 ou mais filhos. Com menos de 2 filhos seu valor é irrelevante (gera o mesmo SQL), mas
ainda assim deve ser enviado. Um where sem filtros é expresso como um grupo vazio:
{ "kind": "group", "logicalOperator": "AND", "children": [] }.
Folha de coluna — kind: "predicate"
Compara uma coluna escalar qualificada por sua tabela.
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
kind | "predicate" | Sim | Discriminador. |
column | ColumnRefDto | Sim | Coluna do predicado. |
comparisonOperator | ComparisonOperatorEnum | Sim | Operador de comparação. |
value | PredicateValue | Depende | Seu formato depende do operador. |
{
"kind": "predicate",
"column": { "table": "user_properties", "column": "country" },
"comparisonOperator": "IN",
"value": ["CL", "MX"]
}Folha de registro — kind: "recordPredicate"
Filtra por uma coluna RECORD REPEATED (um array de structs, como attributes).
Significa que pelo menos um elemento do array satisfaz o sub-filtro.
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
kind | "recordPredicate" | Sim | Discriminador. |
column | ColumnRefDto | Sim | Coluna RECORD REPEATED de uma tabela do from. |
subWhere | Sub-árvore relativa | Sim | Condições sobre os sub-campos do elemento. Não pode ficar vazio. |
{
"kind": "recordPredicate",
"column": { "table": "event_transactions", "column": "attributes" },
"subWhere": {
"kind": "group",
"logicalOperator": "AND",
"children": [
{ "kind": "predicate", "field": "key", "comparisonOperator": "EQUALS", "value": "canal" },
{ "kind": "predicate", "field": "value", "comparisonOperator": "EQUALS", "value": "web" }
]
}
}As condições do subWhere são avaliadas sobre um mesmo elemento do array, e não
sobre o array inteiro. O exemplo acima seleciona linhas que têm um atributo cujo key
é canal e cujo value é web — não linhas que têm um atributo com esse key e
outro, diferente, com esse value.
Quais colunas aceitam um filtro de registro é informado pelo
catálogo: as que vêm com
kind: "record".
Sub-árvore relativa
O subWhere é um grupo AND/OR cujas folhas são resolvidas contra os sub-campos que o
registro declara.
Há uma única diferença em relação à árvore de nível superior, e ela é a origem mais comum de erros:
Dentro de uma sub-árvore relativa os operandos não levam tabela: você escreve
"field": "key", e não "column": { "table": "attributes", "column": "key" }. A folha
usa a chave field (uma string), não column.
Folhas permitidas dentro de uma sub-árvore relativa:
- Folha escalar —
{ "kind": "predicate", "field": string, "comparisonOperator": …, "value"?: … }. Ofielddeve ser um sub-campo escalar do registro. - Registro aninhado —
{ "kind": "recordPredicate", "field": string, "subWhere": … }. Um registro dentro de outro registro; aninha sem limite declarado, desde que o catálogo declare cada nível. - Grupo — o mesmo formato de grupo, para combinar as folhas anteriores com
AND/OR.
Forma de value segundo comparisonOperator
| Operadores | Forma de value | Exemplo |
|---|---|---|
IS_NULL, IS_NOT_NULL | Sem value (omitido) | (omitido) |
IN, NOT_IN | Lista não vazia ScalarValue[] | ["CL", "MX"] |
BETWEEN | Par [min, max] | [10, 20] |
O resto (EQUALS, NOT_EQUALS, GREATER_THAN, LESS_THAN, GREATER_THAN_OR_EQUAL, LESS_THAN_OR_EQUAL, CONTAINS, NOT_CONTAINS, STARTS_WITH, ENDS_WITH) | Escalar único | "ativo" · 42 |
ScalarValue = string | number | boolean. Além disso, cada operador deve ser
compatível com o tipo da coluna (veja regras de validação).
groupBy — colunas de agrupamento
Lista opcional de ColumnRefDto[]. Quando o bloco agrega (declara groupBy ou tem um
agregado no select), o groupBy deve corresponder exatamente às colunas
não agregadas do select (veja regras de validação).
having — filtro sobre agregados (HavingDto)
Mesma estrutura recursiva que where (grupos AND/OR aninhados e a mesma regra de value
por operador), mas a folha opera sobre um agregado, não sobre uma coluna:
- Predicado (folha) —
{ kind: "predicate", aggregate: AggregateDto, comparisonOperator: ComparisonOperatorEnum, value?: PredicateValue }. - Grupo — idêntico ao de
where.
timeWindow — janela temporal (TimeWindowDto)
União discriminada por timeOperator. Limita o bloco a um período de tempo sobre uma
coluna TIMESTAMP do catálogo (reference). É um campo irmão de where, não um
nó da árvore de filtros.
timeOperator | Campos adicionais |
|---|---|
ALL_TIME | (nenhum) — não limitado por tempo. |
IN_THE_LAST | reference: ColumnRefDto, unit: TimeUnitEnum, value: inteiro > 0 |
IN_THE_FIRST | reference: ColumnRefDto, unit: TimeUnitEnum, value: inteiro > 0 |
SINCE | reference: ColumnRefDto, from: string (YYYY-MM-DD) |
BETWEEN | reference: ColumnRefDto, from: string (YYYY-MM-DD), to: string (YYYY-MM-DD) |
TimeUnitEnum: DAYS | WEEKS | MONTHS | YEARS.
Semântica de negócio de cada operador:
ALL_TIME— sem janela; considera todo o histórico.IN_THE_LAST— janela rolante relativa a "agora": os últimosvalueunit(ex.: últimos30 DAYS). Recalculada a cada execução.IN_THE_FIRST— janela relativa à origem do ciclo de vida do usuário (sua data de cadastro): os primeirosvalueunitde vida de cada usuário. É ancorada por usuário, não a uma data fixa.SINCE— a partir da data civilfrom(inclusive).BETWEEN— entrefrometo, ambas datas civis inclusive do dia completo.
As datas civis YYYY-MM-DD (SINCE, BETWEEN) resolvem para o início do dia no
fuso horário do tenant. O detalhe do fuso horário é interno; basta enviar a
data civil.
composedWith[] — composição com outras audiências
Cada elemento (CreateCompositionDto) combina esta definição com outra audiência
via uma operação de conjunto:
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
operandCriteriaId | string (UUID) | Sim | Id da outra audiência (operando). Deve existir. |
setOperator | SetOperatorEnum | Sim | UNION_DISTINCT | UNION_ALL | INTERSECT_DISTINCT. |
Exemplo
Audiência de usuários com 3 ou mais transações COMPLETED nos últimos 90 dias. Projeta
apenas user_id, como a definição padrão da audiência raiz (veja
Interseção com a audiência raiz). É solicitada uma amostra de
50 linhas (limit).
curl -X POST https://api.reten.ai/api/audience-criterias/preview-from-body \
-H "Authorization: Bearer <token>" \
-H "x-tenant-id: <tenant-id>" \
-H "x-project-id: <project-id>" \
-H "Content-Type: application/json" \
-d '{
"queryBlocks": [
{
"order": 0,
"from": { "table": "event_transactions" },
"select": {
"distinct": false,
"items": [
{
"kind": "column",
"column": { "table": "event_transactions", "column": "user_id" }
}
]
},
"timeWindow": {
"timeOperator": "IN_THE_LAST",
"reference": { "table": "event_transactions", "column": "event_date" },
"unit": "DAYS",
"value": 90
},
"where": {
"kind": "group",
"logicalOperator": "AND",
"children": [
{
"kind": "predicate",
"column": { "table": "event_transactions", "column": "status" },
"comparisonOperator": "EQUALS",
"value": "COMPLETED"
}
]
},
"groupBy": [{ "table": "event_transactions", "column": "user_id" }],
"having": {
"kind": "group",
"logicalOperator": "AND",
"children": [
{
"kind": "predicate",
"aggregate": {
"aggregationOperator": "COUNT",
"operand": { "kind": "star" }
},
"comparisonOperator": "GREATER_THAN_OR_EQUAL",
"value": 3
}
]
}
}
],
"limit": 50
}'import axios from 'axios';
const body = {
queryBlocks: [
{
order: 0,
from: { table: 'event_transactions' },
select: {
distinct: false,
items: [
{
kind: 'column',
column: { table: 'event_transactions', column: 'user_id' },
},
],
},
timeWindow: {
timeOperator: 'IN_THE_LAST',
reference: { table: 'event_transactions', column: 'event_date' },
unit: 'DAYS',
value: 90,
},
where: {
kind: 'group',
logicalOperator: 'AND',
children: [
{
kind: 'predicate',
column: { table: 'event_transactions', column: 'status' },
comparisonOperator: 'EQUALS',
value: 'COMPLETED',
},
],
},
groupBy: [{ table: 'event_transactions', column: 'user_id' }],
having: {
kind: 'group',
logicalOperator: 'AND',
children: [
{
kind: 'predicate',
aggregate: {
aggregationOperator: 'COUNT',
operand: { kind: 'star' },
},
comparisonOperator: 'GREATER_THAN_OR_EQUAL',
value: 3,
},
],
},
},
],
limit: 50, // opcional; padrão 100
};
const response = await axios.post(
'https://api.reten.ai/api/audience-criterias/preview-from-body',
body,
{ headers: { Authorization: 'Bearer <token>', 'x-tenant-id': '<tenant-id>', 'x-project-id': '<project-id>' } },
);
const preview = response.data; // IPreviewAudienceCriteriaResultA resposta está documentada em IPreviewAudienceCriteriaResult,
com um exemplo de rows não vazio.
POST /api/audience-criterias/:id/preview
Executa um critério já salvo, referenciado por seu id. A definição não viaja no
corpo: é obtida do critério persistido no projeto ativo. O corpo só carrega limit.
Auth: Obrigatória — permissão audience-criteria:view-sql
Como o anterior, responde 201 Created.
Parâmetros de rota
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
id | UUID | Sim | O id do audience criteria. Deve ser um UUID válido (caso contrário, 400). |
Corpo da requisição
PreviewQueryDto — um único campo, opcional:
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
limit | number (integer) | Não | Tamanho da amostra de rows. Inteiro 1..500. Padrão 100 (veja limit). |
Um corpo vazio ({}) é válido: usa o limit padrão (100).
Exemplo
curl -X POST https://api.reten.ai/api/audience-criterias/f47ac10b-58cc-4372-a567-0e02b2c3d479/preview \
-H "Authorization: Bearer <token>" \
-H "x-tenant-id: <tenant-id>" \
-H "x-project-id: <project-id>" \
-H "Content-Type: application/json" \
-d '{ "limit": 50 }'import axios from 'axios';
const id = 'f47ac10b-58cc-4372-a567-0e02b2c3d479';
const response = await axios.post(
`https://api.reten.ai/api/audience-criterias/${id}/preview`,
{ limit: 50 }, // opcional; padrão 100
{ headers: { Authorization: 'Bearer <token>', 'x-tenant-id': '<tenant-id>', 'x-project-id': '<project-id>' } },
);
const preview = response.data; // IPreviewAudienceCriteriaResultlimit — tamanho da amostra
limit limita apenas quantas linhas a resposta traz em rows (a amostra que você
vê), não o universo correspondente à audiência.
- Intervalo: inteiro 1..500 (menor que 1 ou maior que 500 ⇒
400). - Padrão:
100(PREVIEW_ROW_LIMIT_DEFAULT) quando omitido.
limit governa o tamanho da amostra em rows; totalCount é o universo
completo correspondente à audiência e não é limitado por limit. Preview executa
duas consultas sobre a mesma definição: um SELECT ... LIMIT <limit> para a amostra e um
SELECT COUNT(*) para o total. Por isso você pode ver rows.length = 50 com
totalCount = 4821: rows é um vislumbre, totalCount é o tamanho real da audiência.
Resposta — IPreviewAudienceCriteriaResult
| Campo | Tipo | Descrição |
|---|---|---|
rows | Record<string, unknown>[] | Amostra de linhas reais, limitada por limit. Cada linha traz as colunas que a audiência projeta (seu select, com seus aliases); por isso rows não tem uma forma fixa. Essa projeção precisa ser compatível com a da audiência raiz (veja Interseção com a audiência raiz). |
totalCount | number | Total de linhas correspondentes à audiência, não limitado por limit (o universo completo). |
bytesProcessed | number | Bytes processados pelo BigQuery na execução. Soma os bytes de ambas as consultas (amostra + contagem). |
Sempre distinga rows (a amostra, no máximo limit linhas) de totalCount (o
universo, sem limite). Se totalCount > rows.length, há mais linhas do que a
amostra consegue mostrar.
Exemplo
Resposta 201 ao exemplo acima (limit: 50). A audiência corresponde a 4821 usuários;
rows mostra os primeiros 50 (aqui reduzidos a 3 por brevidade), cada um com a
única coluna projetada (user_id):
{
"rows": [
{ "user_id": "u_9f3a1c" },
{ "user_id": "u_2b7e04" },
{ "user_id": "u_c081ff" }
],
"totalCount": 4821,
"bytesProcessed": 5242880
}As chaves de cada objeto em rows (user_id) vêm do select da audiência. totalCount
(4821) é o universo completo, maior que as 50 linhas da amostra.
Interseção com a audiência raiz
Todo projeto tem uma audiência raiz, e toda outra
audiência do projeto é avaliada dentro dela. O preview executa o mesmo SQL que
Gerar SQL
retorna: para qualquer audiência que não seja a audiência raiz, intersectado com a audiência raiz
do projeto. Por isso rows e totalCount são as linhas correspondentes à audiência dentro da
audiência raiz, e bytesProcessed inclui a parte da consulta que corresponde à audiência raiz.
Não há interseção quando a audiência executada é a própria audiência raiz — :id/preview com
o id da audiência raiz, ou um rascunho de preview-from-body cujo criteriaId é a audiência raiz.
A interseção é posicional (SELECT * nos dois lados): a audiência deve projetar as mesmas
colunas que a audiência raiz, na mesma ordem e com tipos compatíveis — com a definição padrão da
audiência raiz, apenas user_id. Caso contrário, o BigQuery rejeita a consulta ao executá-la e o
preview responde 400 (Query execution failed: <detail>).
Regras de validação
Antes de executar, a definição passa pelas mesmas duas camadas de validação que
Criar, e ambas
retornam 400 Bad Request:
- Validação de DTO (estrutura, tipos, enums, campos obrigatórios,
limitdentro do intervalo).messageé um array de strings e propriedades desconhecidas são rejeitadas (incluindoname/description). - Validação de negócio (a definição deve gerar SQL válido e coerente com o
catálogo).
messageé uma string única com a regra violada.
A validação de negócio roda em ambos os endpoints: preview-from-body valida a
definição no corpo, e :id/preview valida o critério salvo antes de executá-lo. O
catálogo completo de regras e suas mensagens exatas está em
Criar → Regras de validação.
Se a definição passar pelas duas camadas mas a execução no BigQuery falhar —por
exceder o limite de maximumBytesBilled (10 GB), esgotar o timeout de 30 s, ou qualquer
outro erro do motor— a resposta também é 400, com um message no formato
Query execution failed: <detail>.
Respostas de erro
| Status | Descrição |
|---|---|
400 | DTO inválido (campo ausente, tipo incorreto, enum fora do intervalo, limit fora de 1..500, propriedade desconhecida como name/description), uma regra de negócio violada, ou uma falha de execução no BigQuery (Query execution failed: ..., inclui exceder 10 GB ou o timeout de 30 s). Em :id/preview, também se o id não for um UUID válido; em preview-from-body, se o criteriaId não for. |
401 | Ausente ou inválido o Authorization: Bearer. |
403 | O usuário não tem a permissão audience-criteria:view-sql, ou o x-tenant-id não está autorizado. |
404 | Em :id/preview, não existe um audience criteria com esse id no projeto ativo. Em preview-from-body, um operandCriteriaId em composedWith ou o criteriaId não existe no projeto ativo. |
Validar
Valida uma definição de audience criteria e executa um dry-run contra o BigQuery, a partir do corpo (ainda não persistida) ou por id de um critério salvo; retorna se é válida e o custo estimado, sem dados nem SQL.
Filtros de eventos
Selecione eventos com um query-builder, sem escrever SQL, e gere, valide e pré-visualize a consulta resultante.