sponsor-research

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Sponsor research

赞助商研究

Two directions. A show to its sponsors:
arcmira.sponsors(channelId)
ranks recurring sponsors by ad reads with first and last seen dates. A brand to the shows it sponsors:
arcmira.recommendations(entityId, { kind: "sponsored" })
lists each ad read, which the program groups by show.
Run each program with
arcmira_execute_read
;
arcmira_describe
has the method reference.
两个方向。由节目查其赞助商:
arcmira.sponsors(channelId)
按广告口播次数对反复出现的赞助商进行排名,并给出首次和最后出现日期。由品牌查它赞助的节目:
arcmira.recommendations(entityId, { kind: "sponsored" })
列出每次广告口播,再由程序按节目分组。
使用
arcmira_execute_read
运行每个程序;
arcmira_describe
提供方法参考。

When to use

使用场景

  • who sponsors a show, how many ad reads, since when, still active
  • which shows a brand sponsors or advertises on, and how often
  • sponsors two shows share (sponsors of each, then intersect by entity.id)
  • 谁赞助了某个节目、有多少次广告口播、从何时开始、是否仍在投放
  • 某个品牌赞助或宣传了哪些节目,以及投放频率
  • 两个节目有哪些共同的赞助商(分别获取各自的赞助商,再按 entity.id 取交集)

Pick the entity the user meant

确定用户所指的实体

Users give names; filters take ids only (ent_..., UC..., 11-character video ids), and a name where an id belongs throws
id_required
.
  1. Resolve the exact name the user said, with their own words about it as
    context
    (a bare "Theo" has none).
  2. best
    and
    suggested
    give the id. A
    suggested
    pick is an assumption: the answer names it, with
    suggested.evidence
    as the reason.
  3. ask
    : several entities fit, and
    ask.options
    goes back to the user. No answer at all: the name is not in the index.
For this task:
  • A show resolves with
    { type: "channel" }
    ; its id is
    youtube_channel_id
    (a UC id).
  • A brand resolves with no type (a company can be typed product). A sponsor is a company: a person or a topic with the same name ("Freddie Mercury") is not the brand.
  • When two company rows compete, the one with ad reads is the sponsor: run the brand program for each and keep the one with reads.
用户提供名称;过滤器只接受 id(
ent_...
、
UC...
、11 位 video id),如果应填 id 的位置填入名称,则会抛出
id_required
。
  1. 解析用户所说的准确名称,并将用户自己对该名称的描述作为
    context
    (仅说 "Theo" 时没有描述)。
  2. best
    和
    suggested
    会给出 id。选择
    suggested
    属于一种假设:回答中应明确说明,并给出
    suggested.evidence
    作为理由。
  3. ask
    :有多个实体都符合时,
    ask.options
    会返回给用户。完全没有结果:索引中不存在该名称。
对于此任务:
  • 节目按
    { type: "channel" }
    解析;其 id 是
    youtube_channel_id
    (UC id)。
  • 品牌解析时没有 type(公司可能被归类为
    product
    )。赞助商是公司:同名的个人或主题("Freddie Mercury")不是该品牌。
  • 当两个公司记录发生竞争时,有广告口播记录的那个才是赞助商:对每个候选项运行品牌程序,并保留有口播记录的那个。

Worked program

可用程序

Pass each block to
arcmira_execute_read
as one program (a block marked arcmira_execute_write goes to that tool), with the name swapped for the user's. It opens with the pick: set
CONTEXT
to the user's own words about the name. When several entities fit it returns
ask
and runs nothing else. Show those options to the user, then run it again with
ID
set to the pick. Build date windows from
arcmira.daysAgo(n)
and
arcmira.today()
.
将每个代码块作为一个程序传给
arcmira_execute_read
(标记为 arcmira_execute_write 的代码块应传给该工具),并把名称替换为用户的名称。程序首先进行实体选择:将
CONTEXT
设置为用户自己对名称的描述。当有多个实体都符合时,它会返回
ask
且不执行其他操作。向用户展示这些选项,然后将
ID
设置为所选项并再次运行。通过
arcmira.daysAgo(n)
和
arcmira.today()
构建日期窗口。

A show's sponsors

某个节目的赞助商

javascript
const NAME = "TBPN", CONTEXT = undefined, ID = null;   // CONTEXT: the user's own words about the name, never a guess. After an ask, set ID to the picked option's channel_id and run again
const r = ID ? null : await arcmira.resolve(NAME, { type: "channel", context: CONTEXT });
const e = r && (r.best ?? r.suggested);
if (r && !e) return { ask: r.ask && { question: r.ask.question, options: r.ask.options.map(o => ({ ...o, channel_id: r.candidates.find(c => c.id === o.id)?.youtube_channel_id ?? null })) } };
const id = ID ?? e.youtube_channel_id;
const assumed = Boolean(r?.suggested), why = r?.suggested?.evidence ?? null;
const s = await arcmira.sponsors(id);   // limit is a Pro+ filter; slice instead
return {
  show: s.channel.name, channel_id: id, page: s.channel.page, assumed, why, sponsors_total: s.meta.total,
  sponsors: s.sponsors.slice(0, 10).map(x => ({ name: x.entity.name, id: x.entity.id, page: x.entity.page, ad_reads: x.ad_reads, episodes: x.videos, first_seen: x.first_seen, last_seen: x.last_seen, status: x.sponsor_status?.status ?? null })),
};
javascript
const NAME = "TBPN", CONTEXT = undefined, ID = null;   // CONTEXT: the user's own words about the name, never a guess. After an ask, set ID to the picked option's channel_id and run again
const r = ID ? null : await arcmira.resolve(NAME, { type: "channel", context: CONTEXT });
const e = r && (r.best ?? r.suggested);
if (r && !e) return { ask: r.ask && { question: r.ask.question, options: r.ask.options.map(o => ({ ...o, channel_id: r.candidates.find(c => c.id === o.id)?.youtube_channel_id ?? null })) } };
const id = ID ?? e.youtube_channel_id;
const assumed = Boolean(r?.suggested), why = r?.suggested?.evidence ?? null;
const s = await arcmira.sponsors(id);   // limit is a Pro+ filter; slice instead
return {
  show: s.channel.name, channel_id: id, page: s.channel.page, assumed, why, sponsors_total: s.meta.total,
  sponsors: s.sponsors.slice(0, 10).map(x => ({ name: x.entity.name, id: x.entity.id, page: x.entity.page, ad_reads: x.ad_reads, episodes: x.videos, first_seen: x.first_seen, last_seen: x.last_seen, status: x.sponsor_status?.status ?? null })),
};

The shows a brand sponsors, last 90 days

某品牌赞助的节目:最近 90 天

javascript
const NAME = "Mercury", CONTEXT = undefined, ID = null;   // CONTEXT: the user's own words about the name, never a guess. After an ask, set ID to the picked option's id and run again
const r = ID ? null : await arcmira.resolve(NAME, { context: CONTEXT });
const e = r && (r.best ?? r.suggested);
if (r && !e) return { ask: r.ask };
const id = ID ?? e.id;
const assumed = Boolean(r?.suggested), why = r?.suggested?.evidence ?? null;
const after = arcmira.daysAgo(90);
const reads = [];
let cursor, entity, window;
do {
  const page = await arcmira.recommendations(id, { kind: "sponsored", after, limit: 100, cursor });
  entity = page.entity;
  window = page.window;
  reads.push(...page.recommendations);
  cursor = page.has_more ? page.next_cursor : undefined;
} while (cursor && reads.length < 500);
const shows = new Map();
for (const x of reads) {
  const name = x.media.source_channel?.name ?? x.media.channel_id;
  const row = shows.get(name) ?? { show: name, channel_id: x.media.channel_id, ad_reads: 0, episodes: new Set(), latest: "" };
  row.ad_reads += 1;
  row.episodes.add(x.media.video_id);
  if (x.media.published_at > row.latest) row.latest = x.media.published_at;
  shows.set(name, row);
}
return {
  brand: { id, name: entity?.name ?? e?.name ?? null, type: entity?.type ?? e?.type ?? null, assumed, why }, window, ad_reads_total: reads.length,
  shows: [...shows.values()].sort((a, b) => b.ad_reads - a.ad_reads).slice(0, 10).map(s => ({ ...s, episodes: s.episodes.size })),
  sample_read: reads[0] ? { said: reads[0].verbatim_quote, show: reads[0].media.source_channel?.name ?? null, date: reads[0].media.published_at, promo_code: reads[0].promo_code } : null,
};
javascript
const NAME = "Mercury", CONTEXT = undefined, ID = null;   // CONTEXT: the user's own words about the name, never a guess. After an ask, set ID to the picked option's id and run again
const r = ID ? null : await arcmira.resolve(NAME, { context: CONTEXT });
const e = r && (r.best ?? r.suggested);
if (r && !e) return { ask: r.ask };
const id = ID ?? e.id;
const assumed = Boolean(r?.suggested), why = r?.suggested?.evidence ?? null;
const after = arcmira.daysAgo(90);
const reads = [];
let cursor, entity, window;
do {
  const page = await arcmira.recommendations(id, { kind: "sponsored", after, limit: 100, cursor });
  entity = page.entity;
  window = page.window;
  reads.push(...page.recommendations);
  cursor = page.has_more ? page.next_cursor : undefined;
} while (cursor && reads.length < 500);
const shows = new Map();
for (const x of reads) {
  const name = x.media.source_channel?.name ?? x.media.channel_id;
  const row = shows.get(name) ?? { show: name, channel_id: x.media.channel_id, ad_reads: 0, episodes: new Set(), latest: "" };
  row.ad_reads += 1;
  row.episodes.add(x.media.video_id);
  if (x.media.published_at > row.latest) row.latest = x.media.published_at;
  shows.set(name, row);
}
return {
  brand: { id, name: entity?.name ?? e?.name ?? null, type: entity?.type ?? e?.type ?? null, assumed, why }, window, ad_reads_total: reads.length,
  shows: [...shows.values()].sort((a, b) => b.ad_reads - a.ad_reads).slice(0, 10).map(s => ({ ...s, episodes: s.episodes.size })),
  sample_read: reads[0] ? { said: reads[0].verbatim_quote, show: reads[0].media.source_channel?.name ?? null, date: reads[0].media.published_at, promo_code: reads[0].promo_code } : null,
};

A good answer

理想回答

  • Names the brand or show it used, with its type and id, and any look-alike it set aside.
  • Ranks sponsors (or shows) by ad reads and gives the counts, first and last seen dates, and the sponsor status.
  • States the window and the as-of date, and that counts cover the shows Arcmira indexes.
  • Quotes one ad read verbatim with its promo code when there is one, and links each name to the
    page
    the result carries.
  • 明确指出所查询的品牌或节目,并附上其 type 和 id,同时说明排除了哪个相似实体。
  • 按广告口播次数对赞助商(或节目)进行排名,并给出次数、首次和最后出现日期及赞助状态。
  • 说明时间窗口和截至日期,并指出这些计数仅涵盖 Arcmira 已索引的节目。
  • 如存在推广码,则逐字引用一条广告口播及其推广码,并将每个名称链接到结果所附的
    page
    。

Traps

常见陷阱

  • recommendations
    can return
    recommendations_not_enabled
    . Explain the account-access limit and required tier reported by the API; a channel sponsor list does not answer which shows recommend a brand.
  • An ad read is sponsored; an unpaid on-air endorsement is
    kind: "organic"
    . Do not mix them in one count.
  • Page with
    cursor
    until
    has_more
    is false before you count reads; one page is at most 100 rows.
  • recommendations
    可能返回
    recommendations_not_enabled
    。说明 API 报告的账户访问限制和所需套餐层级;频道赞助商列表无法回答哪些节目推荐了某个品牌。
  • 广告口播属于赞助;无偿的口播背书属于
    kind: "organic"
    。不要将两者混入同一计数。
  • 在计数前,使用
    cursor
    持续翻页,直到
    has_more
    为 false;每页最多 100 行。

After the answer

回答之后

Monitors can follow what a research turn found, and each alert uses 25 credits from the account's plan, then its on-demand budget. The
company-watch
skill sets one up.
If anything was wrong, slow, or missing for the user, send one arcmira_feedback.
监控器可以跟踪某次研究找到的内容;每条提醒会先从账户套餐中消耗 25 个 credits,再从其按需预算中扣除。
company-watch
skill 可用于设置监控。
如果有任何内容错误、速度过慢或对用户来说有所缺失,请发送一条 arcmira_feedback。