thoughtleaders-cli 0.9.2__tar.gz → 0.9.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/PKG-INFO +1 -1
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/pyproject.toml +1 -1
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/skills/tl/SKILL.md +0 -6
- thoughtleaders_cli-0.9.3/skills/tl-create-workflow/SKILL.md +245 -0
- thoughtleaders_cli-0.9.3/skills/tl-create-workflow/references/creating-in-app.md +95 -0
- thoughtleaders_cli-0.9.3/skills/tl-create-workflow/references/methodology.md +70 -0
- thoughtleaders_cli-0.9.3/skills/tl-create-workflow/references/pitfalls.md +68 -0
- thoughtleaders_cli-0.9.3/skills/tl-create-workflow/references/workflow-model.md +89 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/src/tl_cli/__init__.py +1 -1
- thoughtleaders_cli-0.9.3/src/tl_cli/commands/workflows.py +159 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/src/tl_cli/main.py +2 -0
- thoughtleaders_cli-0.9.3/tests/test_workflows.py +79 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/.claude-plugin/marketplace.json +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/.claude-plugin/plugin.json +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/.github/dependabot.yml +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/.github/workflows/ci.yml +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/.github/workflows/cli-integration.yml +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/.github/workflows/python-publish.yml +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/.gitignore +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/AGENTS.md +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/API.md +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/CLAUDE.md +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/LICENSE +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/README.md +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/agents/keyword-context-classifier.md +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/agents/keyword-entity-resolver.md +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/agents/keyword-relevance-validator.md +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/agents/tl-analyst.md +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/agents/youtube-comment-classifier.md +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/hooks/hooks.json +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/hooks/scripts/load-tl-skill.mjs +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/hooks/scripts/post-usage.sh +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/hooks/scripts/pre-check.sh +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/skills/tl/references/business-glossary.md +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/skills/tl/references/elasticsearch-schema.md +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/skills/tl/references/firebolt-schema.md +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/skills/tl/references/postgres-schema.md +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/skills/tl-channel-authenticity/.gitignore +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/skills/tl-channel-authenticity/SKILL.md +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/skills/tl-channel-authenticity/references/comment-patterns.md +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/skills/tl-channel-authenticity/references/peer-cohort.md +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/skills/tl-channel-authenticity/references/red-flags.md +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/skills/tl-channel-authenticity/references/scoring.md +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/skills/tl-channel-authenticity/scripts/_io_utf8.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/skills/tl-channel-authenticity/scripts/analyze_channel.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/skills/tl-channel-authenticity/scripts/anomaly_detector.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/skills/tl-channel-authenticity/scripts/comment_analyzer.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/skills/tl-channel-authenticity/scripts/comment_scraper.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/skills/tl-channel-authenticity/scripts/engagement_ratios.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/skills/tl-channel-authenticity/scripts/peer_cohort.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/skills/tl-channel-authenticity/scripts/report.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/skills/tl-channel-authenticity/scripts/resolve_channel.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/skills/tl-channel-authenticity/scripts/score.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/skills/tl-channel-authenticity/scripts/tl_cli.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/skills/tl-channel-authenticity/scripts/video_integrity.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/skills/tl-channel-authenticity/scripts/view_curves.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/skills/tl-keyword-research/SKILL.md +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/skills/tl-keyword-research/references/elasticsearch-content-search.md +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/skills/tl-keyword-research/references/help.md +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/skills/tl-keyword-research/scripts/build_report.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/skills/tl-keyword-research/scripts/expand_entities.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/skills/tl-keyword-research/scripts/fetch_context.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/skills/tl-keyword-research/scripts/probe.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/skills/tl-keyword-research/scripts/search_channels.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/skills/tl-keyword-research/scripts/search_videos.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/skills/tl-keyword-research/scripts/select_keywords.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/skills/tl-save-report/SKILL.md +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/skills/tl-save-report/references/columns_brands.md +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/skills/tl-save-report/references/columns_channels.md +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/skills/tl-save-report/references/columns_content.md +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/skills/tl-save-report/references/columns_sponsorships.md +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/skills/tl-save-report/references/intelligence_filterset_schema.json +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/skills/tl-save-report/references/intelligence_widget_schema.json +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/skills/tl-save-report/references/report_glossary.md +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/skills/tl-save-report/references/sortable_columns.json +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/skills/tl-save-report/references/sponsorship_filterset_schema.json +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/skills/tl-save-report/references/sponsorship_widget_schema.json +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/skills/tl-save-report/references/widgets.md +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/skills/tl-top-partnerships/SKILL.md +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/skills/tl-top-partnerships/scripts/top_partnerships.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/skills/tl-views-guarantee/SKILL.md +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/skills/tl-views-guarantee/scripts/vg.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/src/tl_cli/_completions.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/src/tl_cli/_typer_utils.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/src/tl_cli/auth/__init__.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/src/tl_cli/auth/commands.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/src/tl_cli/auth/login.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/src/tl_cli/auth/pkce.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/src/tl_cli/auth/token_store.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/src/tl_cli/client/__init__.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/src/tl_cli/client/errors.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/src/tl_cli/client/http.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/src/tl_cli/commands/__init__.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/src/tl_cli/commands/_comments_common.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/src/tl_cli/commands/balance.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/src/tl_cli/commands/brands.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/src/tl_cli/commands/bulk_import.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/src/tl_cli/commands/changelog.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/src/tl_cli/commands/channels.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/src/tl_cli/commands/credits.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/src/tl_cli/commands/db.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/src/tl_cli/commands/deals.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/src/tl_cli/commands/describe.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/src/tl_cli/commands/doctor.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/src/tl_cli/commands/matches.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/src/tl_cli/commands/profiles.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/src/tl_cli/commands/proposals.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/src/tl_cli/commands/recommender.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/src/tl_cli/commands/reports.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/src/tl_cli/commands/schema.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/src/tl_cli/commands/setup.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/src/tl_cli/commands/snapshots.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/src/tl_cli/commands/sponsorships.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/src/tl_cli/commands/uploads.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/src/tl_cli/commands/whoami.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/src/tl_cli/config.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/src/tl_cli/filters.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/src/tl_cli/hints.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/src/tl_cli/output/__init__.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/src/tl_cli/output/formatter.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/src/tl_cli/query_history.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/src/tl_cli/self_update.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/tests/__init__.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/tests/test_auth.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/tests/test_brands_winner_channels.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/tests/test_build_report.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/tests/test_channels_lookalike.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/tests/test_db_repeat_warning.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/tests/test_describe.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/tests/test_error_hints.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/tests/test_expand_entities.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/tests/test_filters.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/tests/test_http_auth.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/tests/test_output.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/tests/test_probe.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/tests/test_profiles.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/tests/test_reports.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/tests/test_scripts_executable.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/tests/test_search_channels.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/tests/test_search_videos.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/tests/test_select_keywords.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/tests/test_setup.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/tests/test_sponsorships.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/tests_cli/AGENTS.md +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/tests_cli/conftest.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/tests_cli/test_balance.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/tests_cli/test_db_es.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/tests_cli/test_db_fb.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/tests_cli/test_db_pg.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/tests_cli/test_schema.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/tests_cli/test_whoami.py +0 -0
- {thoughtleaders_cli-0.9.2 → thoughtleaders_cli-0.9.3}/uv.lock +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: thoughtleaders-cli
|
|
3
|
-
Version: 0.9.
|
|
3
|
+
Version: 0.9.3
|
|
4
4
|
Summary: ThoughtLeaders CLI — query sponsorship data, channels, brands, and intelligence
|
|
5
5
|
Project-URL: Homepage, https://thoughtleaders.io
|
|
6
6
|
Project-URL: Repository, https://github.com/ThoughtLeaders-io/thoughtleaders-cli
|
|
@@ -242,7 +242,6 @@ tl channels update 12345 '{"demographic_male_share": 62}'
|
|
|
242
242
|
tl channels update 12345 '{"demographic_geo": {"US": 60, "UK": 12, "CA": 8}}'
|
|
243
243
|
tl channels update 12345 '{"demographic_male_share": 55, "demographic_usa_share": 70}'
|
|
244
244
|
tl channels update 12345 '{"outreach_email": "press@creator.com"}'
|
|
245
|
-
tl channels update 12345 '{"media_selling_network_join_date": "2026-01-15"}'
|
|
246
245
|
```
|
|
247
246
|
|
|
248
247
|
**Channel contact emails.** Besides demographics, `tl channels update` accepts one
|
|
@@ -256,11 +255,6 @@ sending it returns a 400. It is append-only: new addresses are added with the
|
|
|
256
255
|
internal CLI's `tl-internal channels add-email` command (superuser-only), which never
|
|
257
256
|
modifies or removes existing entries.
|
|
258
257
|
|
|
259
|
-
**MSN membership.** `tl channels update` also accepts **`media_selling_network_join_date`** —
|
|
260
|
-
the date the channel joined the Media Selling Network, as a `YYYY-MM-DD` string. This date is
|
|
261
|
-
itself the membership flag: set it to add the channel to MSN (it then reads as `is_msn` and
|
|
262
|
-
appears in MSN-filtered queries), or send `null` to remove the channel from the network.
|
|
263
|
-
|
|
264
258
|
**Profile notes.** `tl profiles update` (superuser only) edits a brand/publisher profile's
|
|
265
259
|
**`superuser_notes`** — the internal free-text notes field on the customer record
|
|
266
260
|
(`thoughtleaders_profile.superuser_notes`, max 2500 chars). Send a string to set, `null` to
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: tl-create-workflow
|
|
3
|
+
tl-blurb: design & stand up a sponsorship pipeline (workflow) from a goal
|
|
4
|
+
description: >
|
|
5
|
+
Turn a sponsorship / sourcing goal into a structured, data-populated
|
|
6
|
+
**Workflow** — an ordered funnel of report-stages that channels (or brands)
|
|
7
|
+
move through, e.g. Sourced → Qualified → Get face on screen → Reach out →
|
|
8
|
+
Contacted → Sold. Invoke when the user wants to build or set up a workflow or
|
|
9
|
+
pipeline, design an outreach / acquisition funnel for a brand or campaign,
|
|
10
|
+
turn an existing report into a workflow, or organise channel sourcing into
|
|
11
|
+
stages. Triggers: "create a workflow", "build a pipeline / funnel", "set up
|
|
12
|
+
outreach for <brand>", "turn this report into a workflow", "organise my
|
|
13
|
+
sourcing into stages", "workflow for finding channels to sponsor <brand>",
|
|
14
|
+
"build an acquisition funnel". It designs the funnel from the goal + the TL
|
|
15
|
+
methodology, sources the entry stage with real data (delegating to
|
|
16
|
+
tl-keyword-research / tl channels / tl recommender / guide-brand research),
|
|
17
|
+
defines each stage as a query-or-list report, and creates it with
|
|
18
|
+
"tl workflow create" (or, until the backend endpoint is deployed, hands back the
|
|
19
|
+
create-ready blueprint + in-app assembly steps). Also answers
|
|
20
|
+
HELP asks about how workflows work ("how do workflows work", "what's a
|
|
21
|
+
query vs a list stage", "explain workflow stages") for free.
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
# tl-create-workflow — a sponsorship goal → a populated pipeline
|
|
25
|
+
|
|
26
|
+
Turn a fuzzy goal ("I need channels to sponsor **Magic Spoon**", "set up our
|
|
27
|
+
outreach funnel", "organise my sourcing") into a **Workflow**: an ordered chain
|
|
28
|
+
of report-**stages** that entities move through, with the **entry stage already
|
|
29
|
+
populated with the right channels** and every stage typed correctly. The value
|
|
30
|
+
is not drawing boxes — it's (a) designing the funnel from the **ThoughtLeaders
|
|
31
|
+
methodology** rather than a generic CRM template, (b) **sourcing the entry
|
|
32
|
+
stage with real data** so the pipeline starts full, not empty, and (c) getting
|
|
33
|
+
the **query-vs-list mechanics right** so the workflow doesn't break the way
|
|
34
|
+
hand-built ones do.
|
|
35
|
+
|
|
36
|
+
A workflow is **not a new kind of object** — every stage IS a saved Report
|
|
37
|
+
(campaign), chained in order. Understanding that is the whole game; read
|
|
38
|
+
`references/workflow-model.md` before you design anything.
|
|
39
|
+
|
|
40
|
+
> `<SKILL_DIR>` below is this skill's directory (the one holding `SKILL.md`).
|
|
41
|
+
|
|
42
|
+
## Hard rules
|
|
43
|
+
|
|
44
|
+
- **A stage is a Report.** A workflow = ordered Reports linked by
|
|
45
|
+
`workflow_step_number`. There is no separate "stage" object. Design in terms
|
|
46
|
+
of reports.
|
|
47
|
+
- **The entry stage is a QUERY; every later stage is a LIST.** This is the
|
|
48
|
+
single most important rule and the #1 cause of broken hand-built workflows —
|
|
49
|
+
see `references/workflow-model.md` (query vs list) and
|
|
50
|
+
`references/pitfalls.md`. Never make stage 2+ a query.
|
|
51
|
+
- **Creating the workflow.** `tl workflow create --file <blueprint.json>` builds
|
|
52
|
+
it in one call — it POSTs `{name, report_type, steps}` to the Bearer endpoint
|
|
53
|
+
`/api/cli/v1/workflows/build` (the twin of the web builder). The command ships
|
|
54
|
+
in this repo; the endpoint ships with backend **PR #4192** — **until that is
|
|
55
|
+
deployed the command errors**, and the user stands the workflow up in the web
|
|
56
|
+
app from the blueprint (Convert → Add stage). Both paths are in
|
|
57
|
+
`references/creating-in-app.md`. **Never claim a workflow was created unless a
|
|
58
|
+
`tl workflow create` call actually returned one** — otherwise you prepared a
|
|
59
|
+
blueprint.
|
|
60
|
+
- **Source with real data, never placeholder channels.** The entry stage must
|
|
61
|
+
be filled from the index (delegate to `tl-keyword-research` /
|
|
62
|
+
`tl channels find` / `tl recommender` / guide-brand research), never a made-up
|
|
63
|
+
list. An empty pipeline is a failed deliverable.
|
|
64
|
+
- Do all data processing with the `utf-8` encoding explicitly in any script you
|
|
65
|
+
write.
|
|
66
|
+
|
|
67
|
+
## Setup check
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
tl whoami # confirms the CLI is authed and shows plan/limits
|
|
71
|
+
```
|
|
72
|
+
If this errors, tell the user to run `tl auth login` (or set `TL_API_KEY`).
|
|
73
|
+
Sourcing stages needs intelligence access on the org's plan; if `tl whoami`
|
|
74
|
+
shows no intelligence flag, say so — you can still design the funnel, but you
|
|
75
|
+
can't populate it from the index.
|
|
76
|
+
|
|
77
|
+
## When to invoke / skip
|
|
78
|
+
|
|
79
|
+
**Invoke** when the user wants to **stand up a pipeline**: build/set up a
|
|
80
|
+
workflow, design an outreach or acquisition funnel for a brand/campaign, turn a
|
|
81
|
+
report into a workflow, or organise sourcing into stages.
|
|
82
|
+
|
|
83
|
+
**Skip when:**
|
|
84
|
+
- They just want to *find* channels/brands/videos → `tl channels find`,
|
|
85
|
+
`tl-keyword-research`, `tl recommender`. (You'll *use* these, but a lookup
|
|
86
|
+
alone isn't a workflow.)
|
|
87
|
+
- They want to persist one flat list/report they already have →
|
|
88
|
+
`tl-save-report`.
|
|
89
|
+
- They're asking about an **existing** workflow's data (counts, who's in which
|
|
90
|
+
stage) → query it with `tl` directly.
|
|
91
|
+
|
|
92
|
+
## Help mode — explain workflows on request, for free
|
|
93
|
+
|
|
94
|
+
When the user asks what a workflow is, how stages work, query vs list, or "how
|
|
95
|
+
do I build one" as a *question* (not a request to build): **run nothing**. Read
|
|
96
|
+
`references/workflow-model.md` (+ `references/pitfalls.md` for the gotchas) and
|
|
97
|
+
explain, sized to the ask. Close by offering to design one. Mid-run questions
|
|
98
|
+
get the same treatment — answer, then resume.
|
|
99
|
+
|
|
100
|
+
## The build (you orchestrate; the tl CLI + sibling skills do the data work)
|
|
101
|
+
|
|
102
|
+
| Stage | What happens | Tooling |
|
|
103
|
+
|---|---|---|
|
|
104
|
+
| 0 Frame | goal, entity type, funnel shape, stage list — interview, don't assume | you + `references/methodology.md` |
|
|
105
|
+
| 1 Source the entry stage | fill stage 1 with the right channels/brands (a QUERY) | `tl-keyword-research` · `tl channels find` · `tl recommender` · guide-brand research |
|
|
106
|
+
| 2 Define the stages | each stage as a report config (query for stage 1, lists after) | you + `references/workflow-model.md` |
|
|
107
|
+
| 3 Blueprint | emit the create-ready plan: stage names, types, the entry filter, links | you |
|
|
108
|
+
| 4 Assemble | the exact in-app steps to build it (Convert → Add stage → link) | `references/creating-in-app.md` |
|
|
109
|
+
| 5 Deliver | blueprint + entry-stage report link + how to work the funnel | `tl-save-report` (for the entry report) |
|
|
110
|
+
|
|
111
|
+
**Narrate the run** — one line per stage transition, and surface every
|
|
112
|
+
assumption so the user can correct it. Sourcing spends credits (it's real ES
|
|
113
|
+
work); say roughly how much as you go, exactly like `tl-keyword-research`.
|
|
114
|
+
|
|
115
|
+
### Stage 0 — Frame the funnel (interview; never assume)
|
|
116
|
+
|
|
117
|
+
Two things decide everything, and both are the user's:
|
|
118
|
+
|
|
119
|
+
1. **The goal & entity.** What is this pipeline *for*, and does it move
|
|
120
|
+
**channels** (usual), **brands**, or **sponsorships**? "Find channels to
|
|
121
|
+
sponsor Magic Spoon" → a channel-acquisition funnel. "Work our brand
|
|
122
|
+
prospects" → a brand funnel. The entity type fixes the workflow's
|
|
123
|
+
`report_type` and can't be mixed later.
|
|
124
|
+
2. **The funnel shape.** How many stages and what they mean. Don't invent a
|
|
125
|
+
generic "Lead → MQL → SQL" — derive it from the **ThoughtLeaders
|
|
126
|
+
methodology** (`references/methodology.md`): the real sourcing funnel is
|
|
127
|
+
*find the pool → qualify on value-vs-price → enrich (face-on-screen,
|
|
128
|
+
contacts) → outreach → pipeline (proposed/pending/sold)*. Offer the canonical
|
|
129
|
+
funnel below and let them cut/rename stages — the huddle's real stages are
|
|
130
|
+
good defaults:
|
|
131
|
+
|
|
132
|
+
> **Sourced** (query) → **Qualify** (list) → **Get face on screen** (list) →
|
|
133
|
+
> **Reach out** (list) → **Contacted** (list) → **Proposed** (list)
|
|
134
|
+
|
|
135
|
+
Stage names are just report titles — pick names the team will recognise
|
|
136
|
+
(they persist on the campaign). Fewer, meaningful stages beat many empty
|
|
137
|
+
ones.
|
|
138
|
+
|
|
139
|
+
State the goal, entity, and stage list back to the user before sourcing
|
|
140
|
+
anything.
|
|
141
|
+
|
|
142
|
+
### Stage 1 — Source the entry stage (the QUERY)
|
|
143
|
+
|
|
144
|
+
Stage 1 is the **pool**: the channels the funnel starts from, selected by a
|
|
145
|
+
*filter* (a query), not an explicit list. Pick the sourcing path from the goal —
|
|
146
|
+
this is where the methodology becomes data:
|
|
147
|
+
|
|
148
|
+
- **Sponsor a specific brand / product** → find the brand's category and its
|
|
149
|
+
**guide brands** (proven sponsors / competitors), then their **winner
|
|
150
|
+
channels** (TRUE renewals — the real signal), then **look-alikes**. Use
|
|
151
|
+
`tl brands` research + `tl channels similar` / `tl recommender`.
|
|
152
|
+
- **A topic / niche** ("cooking channels for a kitchenware brand") →
|
|
153
|
+
**`tl-keyword-research`** to turn the topic into a validated content filter +
|
|
154
|
+
the channels it selects. Take its `report_link` / filter set as stage 1.
|
|
155
|
+
- **A known shortlist** → then stage 1 is really a *list*, and a workflow may be
|
|
156
|
+
overkill — say so; `tl-save-report` might be all they need.
|
|
157
|
+
|
|
158
|
+
Deliver stage 1 as a **query report** (a filter set), and — because it's the
|
|
159
|
+
entry — it's fine and correct for it to be a query. Populate it, eyeball the
|
|
160
|
+
count and a sample, and confirm the breadth with the user (too broad → narrow
|
|
161
|
+
the filter; too thin → widen), exactly like keyword-research's breadth check.
|
|
162
|
+
|
|
163
|
+
### Stage 2 — Define the stages (query first, lists after)
|
|
164
|
+
|
|
165
|
+
For each downstream stage, the report is a **list**: it starts empty and fills
|
|
166
|
+
as the user bulk-selects entities in the previous stage and **Moves** them
|
|
167
|
+
forward. You don't pre-populate lists — you just create the (empty) list
|
|
168
|
+
reports with the right names and types.
|
|
169
|
+
|
|
170
|
+
- **Types must alternate correctly:** stage 1 = query; stages 2..N = lists.
|
|
171
|
+
Re-check `references/workflow-model.md` if unsure how the platform infers
|
|
172
|
+
query-vs-list from the FilterSet.
|
|
173
|
+
- **Columns per stage:** if a stage needs a specific column the team acts on
|
|
174
|
+
(e.g. *Face On Screen* on the "Get face on screen" stage, *Outreach email* on
|
|
175
|
+
"Reach out"), note it — columns are set per report.
|
|
176
|
+
- **Linked reports (include/exclude), sparingly:** a stage can pull in another
|
|
177
|
+
report's entities (e.g. exclude "no email / captcha"). Keep this to **≤1–2
|
|
178
|
+
layers of nesting** — deep chains are the documented performance + confusion
|
|
179
|
+
trap (`references/pitfalls.md`). Prefer a flat stage over a clever nest.
|
|
180
|
+
|
|
181
|
+
### Stage 3 — Emit the blueprint
|
|
182
|
+
|
|
183
|
+
Hand the user a compact, create-ready plan:
|
|
184
|
+
|
|
185
|
+
```
|
|
186
|
+
Workflow: "Magic Spoon — channel sourcing" (report_type: channels)
|
|
187
|
+
1. Sourced [QUERY] ← <entry filter summary> · ~<N> channels · <report_link>
|
|
188
|
+
2. Qualify [list] empty; move channels that pass value-vs-price
|
|
189
|
+
3. Get face on screen [list] empty; column: Face On Screen
|
|
190
|
+
4. Reach out [list] empty; column: Outreach email; exclude → "No email / captcha"
|
|
191
|
+
5. Contacted [list] empty
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
Include the **entry report link** (from keyword-research / `tl reports create`)
|
|
195
|
+
so stage 1 exists as a real, openable report before assembly.
|
|
196
|
+
|
|
197
|
+
### Stage 4 — Assemble in the web app
|
|
198
|
+
|
|
199
|
+
Workflows are built in-app (no CLI endpoint). Walk the user through
|
|
200
|
+
`references/creating-in-app.md`:
|
|
201
|
+
|
|
202
|
+
1. Open the **entry (Sourced) report** → **Convert to workflow** → name it. That
|
|
203
|
+
report becomes **stage 1**.
|
|
204
|
+
2. **Add stage** for each downstream stage, in order, with the names from the
|
|
205
|
+
blueprint (they save on the campaign — renames persist).
|
|
206
|
+
3. For any stage with a **linked report** (e.g. exclude "no email"), add it on
|
|
207
|
+
that stage — keep nesting shallow.
|
|
208
|
+
4. Set per-stage **columns** where noted.
|
|
209
|
+
5. Work the funnel: on a stage, **filter** (e.g. by *Face On Screen*),
|
|
210
|
+
**bulk-select**, **Move** to the next stage. Moving is non-destructive.
|
|
211
|
+
|
|
212
|
+
### Stage 5 — Deliver
|
|
213
|
+
|
|
214
|
+
Show: the funnel (stages, types, per-stage columns/links), the **entry-stage
|
|
215
|
+
report link** (populated), and the one-paragraph "how to work this funnel"
|
|
216
|
+
(filter → select → move). Offer to **save the entry report** via
|
|
217
|
+
`tl-save-report` if it isn't already saved. Never save or create anything the
|
|
218
|
+
user didn't ask for.
|
|
219
|
+
|
|
220
|
+
## Cost
|
|
221
|
+
|
|
222
|
+
Framing and blueprinting are free (no queries). **Sourcing stage 1 spends
|
|
223
|
+
credits** — that's real ES work delegated to `tl-keyword-research` /
|
|
224
|
+
`tl channels` / `tl recommender`; their own costs apply (keyword-research: ~10–20
|
|
225
|
+
credits quick, ~60–120 deep). Run `tl describe show db` for live rates. The
|
|
226
|
+
in-app assembly costs nothing (it's the user clicking in the platform).
|
|
227
|
+
|
|
228
|
+
## Self-check before you finish
|
|
229
|
+
|
|
230
|
+
1. You established the **goal**, the **entity type** (channels / brands /
|
|
231
|
+
sponsorships → the workflow's `report_type`), and the **stage list** with the
|
|
232
|
+
user — derived from the methodology, not a generic CRM funnel — and stated
|
|
233
|
+
them back before sourcing.
|
|
234
|
+
2. **Stage 1 is a QUERY and it's populated** from real index data (not a
|
|
235
|
+
placeholder list), with its breadth confirmed against the goal (narrowed /
|
|
236
|
+
widened as needed). **Every stage after 1 is a LIST.** No stage 2+ is a query.
|
|
237
|
+
3. Any **linked reports** are ≤1–2 nesting layers; you preferred a flat stage
|
|
238
|
+
over a deep nest, and flagged per-stage **columns** the team acts on.
|
|
239
|
+
4. The blueprint is **create-ready**: named stages, correct types, the entry
|
|
240
|
+
filter summary + a working **report link**, and the in-app assembly steps.
|
|
241
|
+
5. You were explicit that the **Workflow is assembled in the web app** (the CLI
|
|
242
|
+
can't create it) — you prepared it, you didn't claim to have created it.
|
|
243
|
+
6. You narrated the run and its credit spend, and saved / created **nothing**
|
|
244
|
+
without the user's say-so.
|
|
245
|
+
7. If the user requests a diagram of the funnel, create it as an SVG graphic.
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# Creating the workflow
|
|
2
|
+
|
|
3
|
+
**`tl workflow create` builds the workflow from a blueprint in one call** — it
|
|
4
|
+
POSTs `{name, report_type, steps}` to the Bearer endpoint
|
|
5
|
+
`/api/cli/v1/workflows/build` (the twin of the web "New Workflow" builder). The
|
|
6
|
+
result is the same `Workflow` / stage-`Campaign` / `FilterSet` objects the rest of
|
|
7
|
+
the platform uses, so it shows up in the web app's workflow list/detail
|
|
8
|
+
immediately, where the team moves / edits / duplicates it.
|
|
9
|
+
|
|
10
|
+
> **Availability.** The `tl workflow` command ships in this repo; the endpoint it
|
|
11
|
+
> calls ships with backend **thoughtleaders PR #4192** (`create_full_workflow`).
|
|
12
|
+
> Until that backend change is deployed, `tl workflow create` returns an error —
|
|
13
|
+
> use the **manual in-app assembly** at the bottom of this file. The blueprint is
|
|
14
|
+
> the exact same input either way, so nothing is wasted.
|
|
15
|
+
|
|
16
|
+
## Create it directly (preferred)
|
|
17
|
+
|
|
18
|
+
1. **Build + save the entry (Sourced) report first**, so it exists with an **id**.
|
|
19
|
+
It's a *query* report populated by this skill (`tl-keyword-research`,
|
|
20
|
+
`tl channels`, `tl recommender`, or `tl reports create`) and saved
|
|
21
|
+
(`tl-save-report` / `tl reports create`). This is the only stage that starts
|
|
22
|
+
with data, and it must be a saved **query** so the stage stays live.
|
|
23
|
+
2. **Write the blueprint to a file** and run `tl workflow create`:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
tl workflow create --file blueprint.json # add --yes to skip the confirm
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
`blueprint.json`:
|
|
30
|
+
|
|
31
|
+
```json
|
|
32
|
+
{
|
|
33
|
+
"name": "Q3 Creator Outreach",
|
|
34
|
+
"report_type": 3,
|
|
35
|
+
"steps": [
|
|
36
|
+
{ "title": "Sourced", "include_report_ids": [<entryReportId>], "exclude_report_ids": [] },
|
|
37
|
+
{ "title": "Qualify", "include_report_ids": [], "exclude_report_ids": [] },
|
|
38
|
+
{ "title": "Get face on screen", "include_report_ids": [], "exclude_report_ids": [] },
|
|
39
|
+
{ "title": "Reach out", "include_report_ids": [], "exclude_report_ids": [] }
|
|
40
|
+
]
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
- `report_type`: **1** content · **2** brands · **3** channels · **8** sponsorships.
|
|
45
|
+
- Stages are created **in order**; the first is the entry stage (link the saved
|
|
46
|
+
query report via `include_report_ids`), the rest are empty **lists** channels
|
|
47
|
+
move into. Keep any linked-report nesting shallow (≤1–2).
|
|
48
|
+
- Only reports you may edit are linked (others are dropped); the workflow is
|
|
49
|
+
owned by you. One atomic call creates the workflow + stage campaigns +
|
|
50
|
+
include/exclude report links + the exclude-earlier-stages chaining.
|
|
51
|
+
- Use `--config '<json>'` for inline JSON, or `--name` / `--report-type` to
|
|
52
|
+
supply/override those fields. `--json` / `--toon` for machine output.
|
|
53
|
+
3. The command prints the new workflow **id** and an **"Open in app"** link
|
|
54
|
+
(`/#/workflows/<report_type>/<id>`). Hand that to the user to work the funnel:
|
|
55
|
+
on a stage, filter → bulk-select → **Move** to the next stage (Move / Remove
|
|
56
|
+
are non-destructive; moved channels leave the source stage).
|
|
57
|
+
|
|
58
|
+
## The endpoints (reference)
|
|
59
|
+
|
|
60
|
+
| Action | Request | Auth |
|
|
61
|
+
|--------|---------|------|
|
|
62
|
+
| **Build a full workflow** (`tl workflow create`) | `POST /api/cli/v1/workflows/build` · `{ name, report_type, steps[] }` | **Bearer (CLI)** |
|
|
63
|
+
| Convert one report → 1-stage workflow | `POST /api/workflows` · `{ campaignId, workflowName }` | session |
|
|
64
|
+
| Add a stage | `POST /api/workflows/add-step` · `{ campaignTitle, workflowId }` | session |
|
|
65
|
+
| Delete a stage (any same-org collaborator) | `DELETE /api/workflows/delete-step?stepId=` | session |
|
|
66
|
+
| Rename / delete the workflow (delete is owner-only) | `PATCH` / `DELETE /api/workflows/:id` | session |
|
|
67
|
+
| Fetch a workflow + stages | `GET /api/workflows/:id` | session |
|
|
68
|
+
| Link a report / move entities on a stage | `PATCH` the stage filterset's `add_relation` action | session |
|
|
69
|
+
|
|
70
|
+
Only the **build** endpoint is on the CLI's Bearer surface; the rest are the web
|
|
71
|
+
app's session-authenticated management routes (used from the web UI).
|
|
72
|
+
|
|
73
|
+
## Assemble it in the web app (fallback until the endpoint is live)
|
|
74
|
+
|
|
75
|
+
If the build endpoint isn't deployed yet, the user stands the workflow up from
|
|
76
|
+
the blueprint by hand — same design, more clicks:
|
|
77
|
+
|
|
78
|
+
1. Open the saved entry report → **Convert to workflow** → name it. It becomes
|
|
79
|
+
**stage 1**.
|
|
80
|
+
2. **Add stage** for each downstream stage, in blueprint order (each is an empty
|
|
81
|
+
**list**; names persist across reloads).
|
|
82
|
+
3. **Link** supporting include/exclude reports where the blueprint calls for it
|
|
83
|
+
(nesting ≤1–2 layers).
|
|
84
|
+
4. Set per-stage **columns** the team acts on (Face On Screen, Outreach email).
|
|
85
|
+
5. **Work the funnel:** on a stage, filter → select → **Move** to the next stage.
|
|
86
|
+
|
|
87
|
+
## What to hand the user
|
|
88
|
+
|
|
89
|
+
- The **entry report link** (populated, openable).
|
|
90
|
+
- Either the **"Open in app" workflow link** (from `tl workflow create`) or the
|
|
91
|
+
**blueprint + in-app assembly steps** (fallback).
|
|
92
|
+
- The one-line "how to work the funnel": *filter a stage → select → Move to next.*
|
|
93
|
+
|
|
94
|
+
Never claim a workflow was created unless a `tl workflow create` call actually
|
|
95
|
+
returned one — otherwise you prepared a blueprint.
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# Funnel design — the ThoughtLeaders methodology, not a generic CRM
|
|
2
|
+
|
|
3
|
+
Don't design a workflow like a generic sales CRM ("Lead → MQL → SQL → Won").
|
|
4
|
+
Design it from how ThoughtLeaders actually sources and closes sponsorships. The
|
|
5
|
+
funnel stages fall out of the methodology.
|
|
6
|
+
|
|
7
|
+
## The sourcing methodology (how the pool is found)
|
|
8
|
+
|
|
9
|
+
The core play for finding the right channels for a brand:
|
|
10
|
+
|
|
11
|
+
1. **Identify the brands** — through competitor research and **Guide Brands**
|
|
12
|
+
(brands that are *proven* sponsors in the category). A guide brand is a
|
|
13
|
+
working example of "who already pays to sponsor this kind of content".
|
|
14
|
+
2. **Find the winner channels** — the channels those guide brands *renewed*
|
|
15
|
+
with. A **TRUE renewal** (the brand came back and paid again) is the real
|
|
16
|
+
signal that the channel converts, not a vanity metric.
|
|
17
|
+
3. **Find look-alike channels** — channels similar to the winners (same
|
|
18
|
+
audience/niche/shape) that haven't been booked yet. This is the addressable
|
|
19
|
+
pool.
|
|
20
|
+
4. **Analyse value vs price** — for each candidate, is the projected value
|
|
21
|
+
(views, audience fit) worth the price? This is the qualification gate.
|
|
22
|
+
|
|
23
|
+
The entry stage of a workflow is the output of steps 1–3 (the look-alike pool),
|
|
24
|
+
expressed as a **query**. Qualification (step 4) is the first downstream list
|
|
25
|
+
stage.
|
|
26
|
+
|
|
27
|
+
## Terminology to keep straight (TL uses its own words)
|
|
28
|
+
|
|
29
|
+
- **Brands** = the sponsors (usually companies, sometimes a single product).
|
|
30
|
+
- **Channels** = the creators being sponsored (YouTube channels, sometimes
|
|
31
|
+
podcasts).
|
|
32
|
+
- **Sponsorship** is the umbrella; it narrows through a funnel of its own:
|
|
33
|
+
*Sponsorships ⊃ Matches ⊃ Proposals ⊃ Deals (sold)*.
|
|
34
|
+
- Pricing words: **PV** = Projected Views (a pricing estimate); **VG** = View
|
|
35
|
+
Guarantee (the contractual floor). Don't invent CPM/"margin" language — TL
|
|
36
|
+
says **Net revenue** / **TL profit**, and avoid "flight" / "hero channel".
|
|
37
|
+
- **Send date** = the expected publication date of a sponsored video.
|
|
38
|
+
- Two channel networks exist: **MSN** (the large ~11K opted-in Media Selling
|
|
39
|
+
Network) and **TPP** (the small ~169 directly-managed VIP channels). Sourcing
|
|
40
|
+
usually works over MSN; enrichment tasks ("get face on screen") are often
|
|
41
|
+
assigned to MSN managers.
|
|
42
|
+
|
|
43
|
+
## The canonical acquisition funnel
|
|
44
|
+
|
|
45
|
+
A good default channel-acquisition workflow, with each stage's type and the
|
|
46
|
+
column the team acts on. Offer this, then let the user cut / rename / reorder.
|
|
47
|
+
|
|
48
|
+
| # | Stage | Type | What it means | Acted-on column |
|
|
49
|
+
|---|-------|------|---------------|-----------------|
|
|
50
|
+
| 1 | **Sourced** | query | The pool: look-alike channels for the brand's guide-brand winners (or a topic filter). | — |
|
|
51
|
+
| 2 | **Qualify** | list | Passed value-vs-price (and, if relevant, an authenticity check). | Projected views / price |
|
|
52
|
+
| 3 | **Get face on screen** | list | Assigned to MSN managers to fill in face-on-screen + enrich. | Face On Screen |
|
|
53
|
+
| 4 | **Reach out** | list | Has an outreach email; ready to contact. | Outreach email |
|
|
54
|
+
| 5 | **Contacted** | list | Outreach sent. | — |
|
|
55
|
+
| 6 | **Proposed** | list | A proposal is out. | — |
|
|
56
|
+
|
|
57
|
+
Notes:
|
|
58
|
+
- Stages 5–6 mirror the sponsorship sub-funnel (Match → Proposal → Deal); stop
|
|
59
|
+
wherever the team's process stops. Don't add stages the team won't work.
|
|
60
|
+
- For a **brand-prospecting** workflow (report_type = brands) the shape rebases:
|
|
61
|
+
*Prospects (query: brands in a category / competitors of a guide brand) →
|
|
62
|
+
Qualified → Pitching → Won*.
|
|
63
|
+
|
|
64
|
+
## Sizing the pool (breadth)
|
|
65
|
+
|
|
66
|
+
There is no universal right number. A niche brand with a few dozen good
|
|
67
|
+
look-alikes is a complete answer; a broad consumer brand returning a few dozen
|
|
68
|
+
is probably too narrow. State your breadth judgement and offer to narrow/widen —
|
|
69
|
+
exactly the calibration `tl-keyword-research` does. The pool is the query stage;
|
|
70
|
+
everything downstream is a subset of it.
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# Pitfalls — the failure modes hand-built workflows hit
|
|
2
|
+
|
|
3
|
+
These come from real workflows the team built (and abandoned). Design around
|
|
4
|
+
them from the start; most of a good workflow is just not stepping on these.
|
|
5
|
+
|
|
6
|
+
## 1. A query where a list belongs (the big one)
|
|
7
|
+
|
|
8
|
+
Making stage 2+ a **query** instead of a **list** is the #1 breakage. A query
|
|
9
|
+
recomputes its members from the index every time — it has nothing to *hold* the
|
|
10
|
+
entities you move into it, so "moved" channels vanish on the next load. **Only
|
|
11
|
+
the entry stage is a query; everything after it is a list.** If the user wants
|
|
12
|
+
to "filter" a mid-funnel stage, that's a transient **view filter** on the
|
|
13
|
+
list's rows (narrow what's shown so you can bulk-select), not a query stage.
|
|
14
|
+
|
|
15
|
+
## 2. Empty pipeline
|
|
16
|
+
|
|
17
|
+
Delivering a funnel whose entry stage is empty (or filled with placeholder
|
|
18
|
+
channels) is a non-deliverable. The entry stage must be **sourced from real
|
|
19
|
+
index data** — `tl-keyword-research`, `tl channels`, `tl recommender`,
|
|
20
|
+
guide-brand look-alikes — with its breadth sense-checked against the goal.
|
|
21
|
+
|
|
22
|
+
## 3. Over-nesting linked reports
|
|
23
|
+
|
|
24
|
+
A stage can include/exclude other reports, which can themselves include others.
|
|
25
|
+
There's **no depth limit in the platform**, and deep/wide nests resolve
|
|
26
|
+
exponentially (slow) and become impossible to reason about ("this report
|
|
27
|
+
excludes that one, which includes this other one…"). **Cap it at 1–2 layers.**
|
|
28
|
+
Prefer a flat stage with its own filters over a clever nest. Historically people
|
|
29
|
+
added manual exclude-hacks to make a nested workflow usable — that's a smell,
|
|
30
|
+
not a pattern to copy.
|
|
31
|
+
|
|
32
|
+
## 4. Meaningless / churning stage names
|
|
33
|
+
|
|
34
|
+
Stages are reports; their names are the report titles and they **persist** on
|
|
35
|
+
the campaign (a real historical bug reverted them, now fixed). Pick names the
|
|
36
|
+
team already uses for its process ("Get face on screen", "Reach out",
|
|
37
|
+
"Contacted") — not generic CRM labels. Fewer meaningful stages beat many empty
|
|
38
|
+
ones nobody works.
|
|
39
|
+
|
|
40
|
+
## 5. Designing for one person on a shared object
|
|
41
|
+
|
|
42
|
+
A workflow is **shared** across the team by default. Don't design it around one
|
|
43
|
+
AM's private view; design the stages so several people can work them. (The
|
|
44
|
+
platform's own per-user view feature is what lets each person hide the reports
|
|
45
|
+
that aren't theirs — not something you configure here, but keep the shared
|
|
46
|
+
reality in mind when naming/structuring stages.)
|
|
47
|
+
|
|
48
|
+
## 6. Claiming you created it
|
|
49
|
+
|
|
50
|
+
The CLI can't create the Workflow object — you **design, source, and
|
|
51
|
+
blueprint**, and the user assembles it in the app (Convert → Add stage → …).
|
|
52
|
+
Never say "I created your workflow." Say "here's your populated blueprint and
|
|
53
|
+
the steps to stand it up."
|
|
54
|
+
|
|
55
|
+
## 7. Too many stages
|
|
56
|
+
|
|
57
|
+
A funnel with eight stages the team won't actually move channels through is
|
|
58
|
+
worse than four they will. Map stages to the team's *real* process steps and
|
|
59
|
+
stop where the process stops. Every stage is a report someone has to maintain.
|
|
60
|
+
|
|
61
|
+
## Quick checklist
|
|
62
|
+
|
|
63
|
+
- [ ] Entry stage is a **query**, populated from real data, breadth confirmed.
|
|
64
|
+
- [ ] Every later stage is a **list**.
|
|
65
|
+
- [ ] Nesting ≤ 1–2 layers; flat preferred.
|
|
66
|
+
- [ ] Stage names are the team's real process words.
|
|
67
|
+
- [ ] Per-stage columns the team acts on are noted.
|
|
68
|
+
- [ ] You blueprinted + handed off assembly — you didn't claim to have created it.
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# The Workflow data model — read this before designing anything
|
|
2
|
+
|
|
3
|
+
A Workflow looks like a bespoke pipeline object. It isn't. It's a thin wrapper
|
|
4
|
+
over the same **Report** (campaign) objects the platform already has. Get this
|
|
5
|
+
model right and the rest of the skill is easy; get it wrong and you'll design
|
|
6
|
+
workflows that break the way hand-built ones do.
|
|
7
|
+
|
|
8
|
+
## A stage IS a Report
|
|
9
|
+
|
|
10
|
+
- A **Workflow** has a `name`, a `report_type` (content / brands / channels /
|
|
11
|
+
sponsorships), an `owner`, and an ordered set of **steps**.
|
|
12
|
+
- **There is no separate "step" / "stage" object.** A step *is* a `Campaign`
|
|
13
|
+
(the platform's word for a saved Report), linked to the workflow by a
|
|
14
|
+
`workflow` FK + a `workflow_step_number` that gives the order.
|
|
15
|
+
- So "add a stage" = "create a report and hang it on the workflow at position
|
|
16
|
+
N". "Rename a stage" = "rename that report". Everything you know about
|
|
17
|
+
reports applies to stages.
|
|
18
|
+
- A workflow is **typed**: every stage is the same `report_type`. You can't mix
|
|
19
|
+
channels and brands in one workflow.
|
|
20
|
+
|
|
21
|
+
## Query vs list — the distinction that matters most
|
|
22
|
+
|
|
23
|
+
Every report (stage) has a **FilterSet**. Whether a stage behaves as a **query**
|
|
24
|
+
or a **list** is *not a stored flag* — it's implied by what's in that FilterSet:
|
|
25
|
+
|
|
26
|
+
- **QUERY stage** — the FilterSet holds **filter criteria**: keywords, date
|
|
27
|
+
ranges, view/subscriber ranges, categories, content filters. The stage
|
|
28
|
+
*computes* its members by matching the index. It's a live search.
|
|
29
|
+
- **LIST stage** — the FilterSet holds **explicit included / excluded
|
|
30
|
+
entities**: specific channels (or brands) that were put there. The stage *is*
|
|
31
|
+
that set. It doesn't search; it holds.
|
|
32
|
+
|
|
33
|
+
Why it matters for building a workflow:
|
|
34
|
+
|
|
35
|
+
- **The entry stage should be a QUERY.** It's the pool — the funnel needs a way
|
|
36
|
+
to *find* candidates, and a query does that (e.g. "channels matching this
|
|
37
|
+
topic / these guide-brand look-alikes").
|
|
38
|
+
- **Every stage after the entry should be a LIST.** Downstream stages are where
|
|
39
|
+
you *move* entities into as they progress. Moving an entity = adding it to the
|
|
40
|
+
target stage's included list. A downstream stage that's a query has nothing to
|
|
41
|
+
hold what you move into it.
|
|
42
|
+
- A query as anything but the first stage is the classic broken-workflow bug.
|
|
43
|
+
If a user asks for a mid-funnel "query" stage, what they usually want is a
|
|
44
|
+
**filter applied to a list stage's view** (narrow the visible rows) — that's a
|
|
45
|
+
transient view filter, not a query stage. Keep the stage a list.
|
|
46
|
+
|
|
47
|
+
## Moving entities through the funnel
|
|
48
|
+
|
|
49
|
+
- Users advance entities by **bulk-selecting** rows in a stage and clicking
|
|
50
|
+
**Move** (to the next stage) — this adds them to the target stage's included
|
|
51
|
+
list.
|
|
52
|
+
- **Exclude / Remove** puts selected entities on a stage's *exclude* list
|
|
53
|
+
(removes them from that stage's results).
|
|
54
|
+
- Moving and excluding are **non-destructive** to the rest of the stage — they
|
|
55
|
+
add to include/exclude lists, they don't rewrite the whole set. (This was a
|
|
56
|
+
real data-loss bug historically; it's fixed, but design as if every move is a
|
|
57
|
+
targeted add, because that's what it is.)
|
|
58
|
+
|
|
59
|
+
## Linked reports (nesting) — powerful, easy to overuse
|
|
60
|
+
|
|
61
|
+
- A stage can **include or exclude another report's entities** (not just
|
|
62
|
+
individual channels). E.g. a "Reach out" stage that *excludes* a "No email /
|
|
63
|
+
captcha" report so those channels never appear.
|
|
64
|
+
- This nests: report A includes report B, which includes report C… There is **no
|
|
65
|
+
hard depth limit in the platform**, and deep chains are a documented
|
|
66
|
+
performance + comprehension trap (exponential resolution on wide/deep nests).
|
|
67
|
+
- **Design rule: ≤1–2 layers of nesting.** Prefer a flat stage with its own
|
|
68
|
+
filters over a clever multi-level include/exclude chain. If you find yourself
|
|
69
|
+
drawing a nest more than two deep, flatten it.
|
|
70
|
+
|
|
71
|
+
## Columns are per-stage
|
|
72
|
+
|
|
73
|
+
- Each stage (report) has its own **columns**. A "Get face on screen" stage
|
|
74
|
+
wants a *Face On Screen* column; a "Reach out" stage wants an *Outreach email*
|
|
75
|
+
column. Note the acted-on column for each stage in the blueprint — the team
|
|
76
|
+
works off it.
|
|
77
|
+
|
|
78
|
+
## Multi-user
|
|
79
|
+
|
|
80
|
+
- A workflow is **shared** across the team by default — several account managers
|
|
81
|
+
work the same stages. (Per-user saved views — each person hiding the reports
|
|
82
|
+
that aren't theirs — is a platform feature area, not something you configure
|
|
83
|
+
from this skill.)
|
|
84
|
+
|
|
85
|
+
## One-line summary to tell a user
|
|
86
|
+
|
|
87
|
+
> A workflow is an ordered set of reports. The first one is a *search* (a query)
|
|
88
|
+
> that finds your pool; each one after it is a *list* that you move channels
|
|
89
|
+
> into as they move through the funnel.
|