营销运营即代码:在 GitHub 上实现从规划到跟进的活动自动化

GitHub 营销团队用 Issue forms、Labels 和 Actions 把活动筹备自动化,原本手工两三天的活现在一个 Issue 就能自动搭建、每日筛查报名并收尾。

中文
复制
题图:淡紫到浅蓝的渐变背景上,几块半透明的绿色方块与一片绿色点阵错落排布,右上角一颗粉紫色球体、右下角一颗蓝紫色球体

我在日本和韩国负责 GitHub 的市场营销,活动是这项工作的核心:面向企业开发者的系列网络研讨会、东京的社区聚会、首尔仅限受邀者参加的高管闭门会。这个市场的开发者眼下真正需要什么?哪些话题值得占用他们一小时,又该请谁到场?这些问题我可以琢磨一整天。

决策之后的事就另当别论了。活动一旦获批,一套固定流程随即启动:

  • 在活动平台上复制一个落地页。
  • 生成一组带 UTM 参数的链接:每个渠道一条,格式都有讲究。
  • 起草邀请邮件,向负责发送的团队提交申请。
  • 把活动加到两个项目看板上。
  • 活动开始前每天早上:下载报名名单、清洗数据、给相关方发一条状态更新。
  • 活动结束后:导出参会者名单,整理成可上传 CRM 的格式,给相应记录打标签,再写一份报告。

这些任务单拎出来都不难,但每一步都可能贴错链接、漏掉一天,或者拼错一个 campaign 名称——而下游有 15 份报告依赖它。

问题是:我以前是工程师。我的第一份职业是在 Linux 服务器上为企业客户维护数据库。代码手感可能生疏了,但我仍然能一眼看出哪条流水线在等着被自动化。这正是我用上 GitHub Copilot 的地方,你也可以在自己的工作里这么做。

所以代码不是我写的。我把自己的操作手册写下来,交给 GitHub Copilot,在对话中把自动化一点点搭起来。如今,一场过去要手工准备两三天的活动,靠一个 GitHub Issue 就能自行完成搭建,每天早上自动筛查报名者,活动结束后还会自己收尾。

这篇文章会讲清楚它是怎么运作的,以及为什么我认为,只要你的工作涉及在多个工具之间做重复劳动,而这些工具又提供了某种可脚本化的入口(API,哪怕只是一个 CLI),你都能照做。

一场活动就是一个 issue

这个基础想法不是我原创的。GitHub 的市场营销团队本来就习惯每个项目开一个 GitHub Issue。计划、讨论和状态都汇集在这里。Issue 早就是我们工作的基本单位。我做的,是让 issue 自己去干活。

三个 GitHub 原语撑起了整套系统:

  • Issue forms 是申请表。 issue form 不是空白文本框,而是呈现结构化字段:活动名称、日期、地区、campaign 名称、目标受众。每种活动类型对应一个表单,比如线上研讨会和线下活动,它们接入的是同一套机制。
  • Labels 是开关。 event-setup 这样的标签不是分类标记,而是触发器。每条自动化工作流都以一个条件开头,意思就是“只有这个标签存在时才运行”。
  • Actions 是机器。 标签一打上,GitHub Actions 工作流就会触发,从 issue 正文里解析出表单字段,然后去干活。

仓库给开发者的一切,也免费给了我的营销工作流:历史记录、可见性、评审,以及每个决定对应的一个 URL。

有一件事让这一切成为可能,而它跟活动本身毫无关系:我们的活动管理平台提供 API。我们的 CRM 甚至不需要 API——它的官方 CLI 覆盖了我们所有的操作,我也从没为它配过 API key,因为 CLI 通过浏览器登录,认证的事它自己处理。API 也好,CLI 也好,要求是一样的:有一条可脚本化的入口。如果你的重复性工作跑在某个工具上,而这个工具提供了活动平台、CRM、表单构建器、分析服务中的任意一种,那这篇文章里的模式就适用于你。

开发者读到这里,大概已经在组织那个显而易见的反驳:这不是在重复造轮子吗?营销自动化平台是现成的,做得好的话,其中一部分开箱即用就能覆盖。但 APAC 与其说是一个市场,不如说是一堆差异极大的市场,即便在我自己的团队里,工作流也随每个子区域、每个细分市场而变。同一场线上研讨会,这个月可能用日语为东京办,下个月就用韩语为首尔办,细分市场不同,CRM 里的字段不同,对优质线索的定义也不同。要让一个打包好的工具吃下所有这些差异,意味着定制预算、咨询工时,以及等别人的 roadmap。自己动手,用手边已有的工具来做,意味着改一次工作流就是一个 pull request:我描述我想要什么,评审者检查,然后它合入 main 分支——走的正是开发者修改软件的那套流程。

策划一场活动,就是一次对话

流水线在 Issue 出现之前就已经启动。我打开 GitHub Copilot,大致这样说:“我想在 11 月办一场关于 AI 辅助开发的线上研讨会。”

接下来发生的事,由一个叫 AGENTS.md 的文件决定,它放在我们仓库的根目录。这是团队的操作手册,用纯 Markdown 写成,规定了活动怎么命名、财季怎么对应到具体日期、每个地区用哪个时区,以及一封合格的邀请邮件长什么样。GitHub Copilot 读完它,然后找到一场类似的往期活动,按我们的命名规则提出一个活动名,起草两版邀请邮件,再把操作手册要求问的问题抛给我。

把对话放在流水线最前面,本身就是一个设计决定,它一次解决了两个问题。全都自动化,就失去了灵活性;哪天你想让某一场活动稍微不一样,僵硬的流水线根本没有地方表达。可要是全交给人工填,又会出错。对话恰好卡在两者中间。GitHub Copilot 按模板走,所以最终落到 Issue 里的数据是对的,格式也是对的。而因为它是对话,我可以为这一场活动调整细节,又不会弄坏下游的机器。

刚开始时,这段对话发生在终端里的 GitHub Copilot CLI 中。对我来说没问题,但“打开终端”对很多我想拉进这套流程的人来说是一道门槛。有了 GitHub Copilot app,同样的对话现在发生在一个普通的桌面窗口里。门槛从“熟悉 shell”降到了“会打字”。

分工这件事我想说清楚,因为它是全部的关键:GitHub Copilot 起草,我来拍板。每一个活动名、每一行邮件标题、每一个日期,都要我签字才会往下走。对话结束时,GitHub Copilot 带着正确的标签创建 GitHub Issue,从这一刻起,机器接手。

一个标签,一个事件,全流程自动化

event-setup 标签一落到 issue 上,GitHub Actions workflow 就会接手,几分钟内完成过去要花我大半天的事:

  • 在活动平台上复制一场往期活动,生成新的落地页
  • 生成全套带 UTM 参数的 URL:每个渠道一条,格式统一,每次都一样
  • 把邀请邮件生成为 Word 文档并提交到仓库
  • 向负责发邮件和跟踪区域营销的团队开出申请 Issue
  • 把活动加入项目看板并填好字段
  • 在 Issue 上回帖汇总,下一个人打开时一眼就能看到全部信息

报名审核靠定时任务,不靠标签。每天早上,一个 cron 触发的 workflow 会拉取所有进行中活动的最新报名者,并分享清洗后的名单。对于仅限邀请的活动,它还会按我们的标准筛查等候名单(这位报名者是 enterprise 客户的开发者、学生,还是特别想混进我们高管闭门会的竞争对手?),通过之后才会批准。

我最得意的设计是一个叫 DRY_RUN 的开关,存成 setting(用 GitHub 的说法是 repository variable),每个 workflow 运行前都会检查它。打开之后,所有 workflow 照常走流程,但不碰任何外部系统:不创建落地页,不在其他仓库开 issue,不分享名单。一个营销团队要自己动手把本职工作自动化,就得有排练的办法。DRY_RUN 就是那个排练开关,也正是它让我从不怕做实验。

活动结束后,一条 slash command

活动收尾以前是最烦的部分:导出参会者、为 CRM 上传重整列格式、拿公司名去匹配客户记录、再写报告。现在只要两条命令。

/lead-upload 拉取参会名单,整理成 marketing operations 团队做 CRM 上传所需的精确格式,开出申请 Issue,并关闭相关跟踪 issue。/event-report 拉取出席数据和问卷结果,把报告以评论形式发到活动对应的 Issue 上——回到那个承载这场活动一切信息的唯一 URL。

这是 GitHub Copilot agent skills,而我最想让你记住的一点是:一个 skill 就是一个 Markdown 文件。每一个 skill 都是一个 SKILL.md:用文字写下的流程,告诉 GitHub Copilot 该做什么、按什么顺序做、要留意什么。我写的那些读起来就像我以前记在脑子里的 runbook——因为它们本来就是。

会写 runbook,就会写 skill。

Skill 也是让这套系统保持灵活的关键。亚太(APAC)地区没有两个市场的跟进流程是一模一样的。受众不同,细分不同,本地惯例不同,而写死的工作流会把每个市场都塞进同一个模子。用 Markdown 写下的流程是灵活的:每个市场都能把 runbook 改成贴合自身现实的样子,而不用动底层的机制。正因如此,活动结束后的步骤放在 GitHub Copilot skills 里,而不是固定在流水线中。

有一点我们把 skill 当代码来对待:新的 skill 通过 pull request 提交,合并前要经过审查,由一个 CODEOWNERS 文件把审查路由给对应的维护者。带审批流程的营销自动化。治理也是平台白送的。

内置护栏让我敢做实验

我自动化了一套会接触客户数据和 API 凭据的工作流,放在全团队都能看到的仓库里,而我自己几乎没写什么代码。六个月前我会说这种组合太鲁莽。让我改变想法的是,我意识到在我动手之前,已经有太多护栏就位了。

有些护栏是我自己搭的:DRY_RUN 开关、每次 pull request 都会跑的测试套件、每次改动都要代码审查。都是开发者的常规习惯。结果发现,它们保护营销工作和保护软件一样有效。

但最重要的护栏是平台自带的:

  • 带推送保护的密钥扫描。 对我这个位置的人来说,最可怕的场景就是不小心把 API token 提交上去。GitHub 的推送保护会在密钥进入仓库之前拦下这次推送;至于 GitHub 自家的 token,就算真有一个漏了过去,也会被自动吊销。
  • GitHub Copilot 的数据政策。 报名者名单是业务数据,固定脚本会以固定的方式处理它们。但真实工作从来不是完全固定的;有些日子我需要一份没有任何脚本预料到的临时数据切片。因为 GitHub Copilot 的商业版方案不会保留 prompt,也不会用它们训练模型,我可以直接要这份临时分析,而不必去做整个行业都在悄悄做的事:把业务数据粘进旁边标签页里开着的随便哪个消费级聊天机器人。模型本身也是一样:我到底能用哪些模型由组织策略决定,而不是交给我个人判断,所以哪怕是一次临时实验,也跑在公司已经划定的边界之内。这一回,安全的路和方便的路是同一条路。

技能带来的另一件事,几乎算是顺带的结果:每个流程现在都是一个有名字、固定的工作单元,所以我可以按任务来挑模型,从组织已批准的模型里选。快速、便宜的模型负责每天的列表清理;更强的模型起草营销文案。

还有一个真实的失败案例,免得你重蹈覆辙:早晨的筛选工作流曾经悄无声息地挂了五天,才有人发现列表已经过期。你不监控的自动化,更像是一颗带延迟的定时炸弹。给每个定时工作流一个能大声报错的方式,这样你就不会错过它。

从一个任务开始

以下是我的建议,来自一个正在康复的手工劳动者,给另一个。

挑出你一周里最重复的那件事。然后看看它涉及的工具是否有 API 或 CLI。有多少有,你可能会吃惊。

然后做最小的版本:一个收集输入的 issue 表单、一个表示“开始”的标签,以及一个只做一步工作的 Action。或者直接跳过这些,把你的 runbook 写成一个 SKILL.md,让 GitHub Copilot 来执行。用一个 dry-run 开关跑它,直到你信任它为止。再从那里慢慢扩展。

代码不是我写的。我只是把已经知道的东西(工作是怎么完成的)写下来,剩下的交给平台。不管你那个“早晨报名者列表”是什么,它大概只差一份写下来的 runbook,就能自己完成自己。

开始使用:

来源: GitHub Blog← 返回首页