TinyPilot: Month 37

Michael Lynch

TinyPilot:第 37 个月

一句话总结

TinyPilot 如何提高经常性收入?

新来的读者?

你好,我是 Michael(迈克尔),一名软件开发者,也是 TinyPilot 的创始人。TinyPilot 是一家独立的计算机硬件公司。我于 2020 年创办了这家公司,目前月收入为 6 万至 8 万美元,并雇用了另外七名员工。

每个月,我都会发布一篇像这样的复盘,分享我的业务和职业生活的整体进展。

亮点

  • 我思考了为 TinyPilot Pro 增加经常性订阅需要做些什么。
  • 我对使用 Nix 管理开发环境做了进一步的探索。

目标评级

每个月初,我都会宣布我希望完成的事情。以下是我对这些目标的完成情况:

达到 9.8 万美元的销售收入

  • 结果:收入下降了 10%,至 8.4 万美元
  • 评级:C

尽管我们收到了几条新的好评,但收入还是下降了:

我们损失了一部分销售额,因为 Amazon 通过其卡夫卡式的账户健康政策降低了我们商品列表的排名。现在我们已重新获得他们的青睐,销售额也再次回升。

我还从其他创始人那里听说,他们在这个时期都会遇到常规的夏季低谷。TinyPilot 在 2022 年 7 月确实也出现了 11% 的收入下降

TinyPilot 向代工厂转移的进度保持按计划进行

  • 结果:进度已延误了三周。
  • 评级:D

制造进度延误了,因为代工厂的下游供应商需要更多时间来生产电源适配器和 USB 线缆等组件。在过渡期间库存清零之前,我们还有大约三周的缓冲时间,但情况开始变得有些棘手。

这个目标本身设计得并不好,因为截止日期不是我选的,我对它的控制也很有限。我真正能做的最多就是防止事情在 TinyPilot 这边被卡住,并督促代工厂遵守他们的时间表。

花在电子邮件上的时间少于 40%

  • 结果:大部分时间都花在了电子邮件上。
  • 评级:F

我花在电子邮件上的时间远远超出了预期。7 月份我外出度假,而我没有考虑到休假期间会积累多少“邮件债”。

最终,我这个月的大部分时间都花在了回复邮件和审查队友的工作上。

TinyPilot 统计数据

指标2023 年 6 月2023 年 7 月变化
独立访客8,3007,800-500 (-6%)
销售收入$88,378.45$79,635.02-$8,743.43 (-10%)
企业订阅$290.70$290.700
版税$4,399.66$3,777.52-$622.14 (-14%)
总收入$93,068.81$83,703.24-$9,365.57 (-10%)
利润$30,907.55$26,359.62-$4,547.93 (-15%)

尽管收入下降,利润仍保持在 2 万至 3 万美元的范围内。这个数字有些虚高,因为我的开支被人为压低了。随着向代工厂的过渡,我正在逐步停止自己的生产,所以已经不再购买新物料。

令我惊讶的是,尽管出现了那么多新评测,网站访客数还是下降了。看起来 TinyPilot 作为一种营销渠道,已经在 homelab 评测领域饱和了一段时间,所以我应该专注于其他类型的销售和营销。

TinyPilot 如何提高经常性收入?

每当 TinyPilot 的销售陷入低谷,我就开始更多地思考经常性收入。如果能有一份不依赖不断寻找新客户的稳定收入,那该多好。

我很害怕有一天,所有想要 TinyPilot 的人都已经有了一台。到那时我该怎么办?

我从一开始的计划就是让 TinyPilot 拥有经常性收入。客户购买一次硬件,然后通过每年续订一次软件许可证来为持续的软件开发和技术支持提供资金。

问题在于,我从未把 TinyPilot 设置成向客户收取经常性费用的模式。三年过去了,除了少数企业客户之外,我们几乎没有任何经常性收入。

在这篇复盘中,我想思考一下为 TinyPilot 提高经常性收入的可能途径。

TinyPilot Pro 的许可证目前是如何运作的

在 2020 年发布最初的 DIY TinyPilot 套件几周后,我就开始开发 TinyPilot 软件的付费版本。

我为 TinyPilot Pro 构建的首批功能之一就是许可证校验。既然要出售软件的付费版本,我就需要一种方法来检查用户的许可证是否有效。

在设计许可证校验系统的过程中,我意识到,在兼顾创始人其他所有职责的同时,仅编写这一个组件就需要好几个月。如果许可证管理要花我三个月来实现,我还需要再花两个月来实现其他付费功能,才能让客户有令人信服的理由购买 TinyPilot Pro。

公司当时才成立几个月,我不想让用户等待五个月才迎来下一个版本,从而大大拖慢发展势头。

有一篇 Basecamp 的博客文章(现在找不到了)讲到他们如何在还没编写计费软件之前就开始销售他们的 SaaS 产品。(更正:Nathan Coleman(内森·科尔曼)找到了。它出自 Basecamp 的书 Getting Real(《Getting Real》)。)他们的理由是,软件的发票在每月服务期结束时才到期,所以他们在第一笔销售之后还有一个月的时间来研究如何收款。

我为 TinyPilot 采取了类似的策略。我选择了荣誉制度作为执行许可证的方式,并预期自己有一年的时间来实现真正的许可证管理方案。

如今三年过去了,我在 TinyPilot Pro 的许可证执行方面仍然没有任何进展。

在最糟糕的时机执行许可证

我们向客户宣传 TinyPilot 设备附带 12 个月的免费更新。我们肮脏的小秘密是,一旦你在设备上安装了 TinyPilot Pro,你就可以通过设备的网页界面永远更新软件。

TinyPilot 网页应用中更新对话框的截图

TinyPilot 的网页应用允许任何设备获取最新版本的 TinyPilot Pro

TinyPilot Pro 的软件不会跟踪它是否关联着有效许可证。有些用户在 2020 年 8 月购买,如今已经进入了他们一年期许可证的第三年。

绝大多数客户根本没有意识到他们的许可证已经过期。他们理所当然地认为,只要 TinyPilot 继续向他们的设备推送更新,他们的许可证就仍然有效。

客户有时确实会发现许可证已过期,但那往往发生在特别不方便的时候。

TinyPilot 使用 microSD 卡作为存储。microSD 特别容易发生文件系统损坏。当 microSD 上的文件系统损坏时,唯一的解决办法就是从 TinyPilot Pro 磁盘镜像重新烧录 microSD。

为了下载 TinyPilot Pro 镜像,客户需要输入他们的订单信息。在提供镜像之前,我们会检查客户是否仍持有有效许可证。

要求用户输入订单号和电子邮箱以下载 TinyPilot Pro 镜像的表单截图

下载 TinyPilot Pro microSD 镜像页面上的许可证校验

从客户的角度来看,这是一种得知许可证已过期的糟糕方式。他们的文件系统损坏了,TinyPilot 已经打断了他们的工作。要解决这个问题,他们必须亲自走到设备前,取出 microSD 并重新烧录。而这时我们还要向他们再要一笔钱?

如果客户不想购买新镜像,只要联系支持团队,我们仍会向他们提供旧镜像的访问权限。但他们仍需等待最多一个工作日才能得到我们的回复,如果我们正在阻碍他们的工作,这就很糟糕。

这个系统对我们来说也不好,因为对旧版 TinyPilot Pro 的请求会消耗支持资源。而且一旦客户拿到新镜像,他们就会重新坐上“永久免费更新”的列车,因为他们可以在设备的网页界面内继续更新软件。

什么样的经常性订阅才值得付出努力?

任何形式的许可证执行都会很昂贵。至少,我们必须在 TinyPilot 的网页界面中加入让客户输入许可证信息的功能,并且我们需要一台互联网上的服务器,根据许可证判断用户是否有资格获得更新。

实现起来很昂贵,因为这需要数周的开发工作,而且当用户不可避免地发邮件说他们无法访问更新、因为他们删掉了包含订单信息的 TinyPilot 邮件时,支持负担也会增加。

如果我费了这么大的劲,却发现它对续订率没有任何影响呢?

要让许可证续订物有所值,它们每年至少需要产生 3 万美元的额外利润。我估计许可证的支付处理费用约为 3%,因此每次许可证续订能为 TinyPilot 带来约 77 美元的净收入。

要达到每年 3 万美元的许可证额外利润目标,每年至少需要 390 名客户续订他们的许可证(390 × 77 = 3 万美元)。

自 2020 年上线以来,TinyPilot 总共售出了约 5,000 台设备。我们目前每年售出约 2,700 台新设备。要达到 390 名付费订阅者,只需说服现有用户中 7.8% 的人为持续更新付费,这看起来是可行的。

我如何测试客户续订许可证的意愿?

好,那么我必须说服 7.8% 的现有客户购买续订许可证,但在没有投入完整的许可证管理实现之前,我怎么才能知道 7.8% 是否可以实现?

强制恢复出厂设置

今年早些时候,我们不得不把 TinyPilot 的基础操作系统从 Debian Buster 切换到 Debian Bullseye。Raspberry Pi OS 没有受支持的大版本升级方式,所以我们不得不强制每位用户手动重新烧录他们的 microSD 来完成迁移。

我讨厌把这种代价强加给用户,但我们找不到其他选择。一个积极的副作用是,它终结了“永久免费”更新列车。如果用户的许可证已过期,他们必须购买新的 12 个月许可证才能继续接收更新。

我们于 4 月 27 日推出了这一变更,所以我比较了变更前三个月和变更后三个月的许可证续订情况:

售出许可证数许可证收入
1 月 26 日至 4 月 26 日33$2,400
4 月 27 日至 7 月 27 日55$4,469
变化+22 (67%)$2,070 (+86%)

一方面,这些数据令人鼓舞,因为强制付费升级使续订量增加了 67%。另一方面,这些数据也令人担忧,因为三个月内只有 55 名用户续订。我估计约有 2,500 台设备的许可证已过期,也就是说只有 2.2% 的人为更新付了费。

有几个因素使续订率低于原本可能达到的水平:

  • 我们最近的大量工作都集中在让更新体验更快、更少出错上。这很有用,但没有人会为了“让未来的更新更顺畅”而更新。
  • 在恢复出厂设置的过程中升级的摩擦很大。有些用户可能放弃了更新,因为他们不想花 20-30 分钟重置设备。

手动发送过期通知

我这个月有个想法:在客户的许可证过期时发送电子邮件通知。这当然可以实现自动化,但在过度投入自动化之前,我先手动发送了几封邮件,看看是否有人会回复或根据我的邮件购买。

我是 TinyPilot 的创始人 Michael Lynch。我联系您是因为我看到您的一年期 TinyPilot Pro 许可证最近已过期。续订许可证是可选的,但它能让您继续获得 TinyPilot 软件中的新功能和错误修复。我们每两到三个月发布一次更新,您可以在公开的更新日志中查看我们近期的一些工作。续订 TinyPilot Pro 许可证还能让您获得私人电子邮件支持以及公共帮助论坛中的优先支持。作为一家小公司,我们依靠许可证续订来帮助资助软件的改进,所以如果您选择续订,请提前致谢!如果您不想续订,我建议下载一份您有资格获得的最新版 TinyPilot Pro(TinyPilot Pro 2.6.0)。万一您将来需要,该镜像可以让您恢复设备的出厂设置。

为了测试这个想法,我发送了七封邮件,但没有一个收件人续订或回复邮件。样本太小,无法得出结论。如果我需要 7.8% 的客户续订,那么每 12 或 13 名客户中就应有 1 名续订。

我不太愿意继续这个实验,因为有很多因素对它不利:

  • 这些邮件到达时,客户不一定在意是否继续接收 TinyPilot 更新。如果提示出现在 TinyPilot 网页应用中用户点击“更新”按钮的时候,那将是一个更有意义的测试。
  • 有些客户购买 TinyPilot 时使用的邮箱地址表明那是接收垃圾邮件的次要账户,所以他们可能根本看不到我的通知。
  • 这些客户可能会发现,即使不为续订付费,他们也能继续接收新更新,因此他们没有任何续订的动力。

添加自动续订选项

我们目前只提供一次性购买的许可证续订。我还没有探索过经常性订阅选项,因为 Shopify 只对一次性购买提供原生支持。

要在 Shopify 上收取经常性费用,我需要使用第三方 Shopify 应用,而我讨厌这么做。根据我的经验,Shopify 应用质量低下,而且它们要求我共享对客户信息的广泛访问权限,包括那些购买从未涉及第三方集成的客户的信息。

尽管如此,与其他实验相比,自动续订选项在测试客户订阅意愿方面的性价比相当高。如果我只是许可证购买页面上添加另一个选项,比如“或以 9 折购买年度订阅”,它就能告诉我是否有客户愿意订阅。

添加订阅按钮相对容易,而且我们很可能不需要更改任何其他流程或系统,因为订阅会以普通 Shopify 订单的形式出现。

副业项目

What Got Done

我最近一直在试验 Nix,其中一个让我感兴趣的功能是 nix develop。它可以让你创建一个自包含的 shell 环境,其中包含构建和测试项目所需的全部开发工具。

我在各种软件项目中遇到的一个烦恼是维护依赖项的困难。我的项目的依赖项绑定在特定版本上,比如 Go 1.19 或 Node.js 16。每当我必须升级到下一个版本时,搞清楚如何在开发环境中安装它,然后更新持续集成(CI)配置中的版本号,都是一件麻烦事。

更糟糕的是,如果我在同一个系统上有多个项目,为一个项目更新 Node.js 意味着其他项目现在会用到意料之外的 Node.js 和 npm 版本。

nix develop 的承诺是,我可以把依赖项定义在一个地方:一个 Nix flake。例如,如果我需要升级到下一个 Go 版本,我只需更新一个文件,重新运行 nix develop,就会得到一个带有正确 Go 版本的本地 shell。我的 CI 环境也会运行相同的版本。该环境是目录本地的,因此更改软件包版本不会影响同一系统上的任何其他项目。

我开始在 What Got Done 中试验 nix develop,因为它依赖 Go 和 Node.js,而版本管理一直是个痛点。

为 What Got Done 的开发环境使用 Nix 挺有意思,但以下是我目前遇到的障碍:

  • 搞不清楚如何让 Go 的静态二进制构建正常工作,而且解决办法给人的感觉有点像“你应该自己知道这句魔法咒语”。
  • 没有办法轻松指定依赖项的确切版本。
    • 我原以为可以像 Docker 那样声明版本,比如 go:1.19.3,但 Nix 不支持这种语义
    • 对于一个如此注重可复现性的工具,这让我感到惊讶。
    • 我找到的最接近的解决办法是使用第三方工具找到与某个软件包版本关联的 nixpkgs 哈希,然后把你的软件包固定到该 nixpkgs 哈希上。以下是 What Got Done 的一个依赖项的示例。
    • Devbox 解决了这个问题,但那样你只是在间接使用 Nix,而且你还得学会使用 Devbox 构建在 Nix 之上的抽象。
  • 填充 Nix store 慢得难以接受。
    • 有一个 nixos/nix Docker 镜像,我可以在 CircleCI 中很快启动它,但为我的 Nix+Go flake 构建 Nix 环境大约需要两分钟。
    • 这意味着我运行的任何 CI 步骤都必须白白花两分钟来初始化 Nix。
    • 我尝试缓存 Nix store,但它大约有 3 GB,CircleCI 下载和解压大约需要两分钟。我猜想 CircleCI 把它的缓存文件存储在 Amazon S3 上,所以除非缓存大小小于 1 GB,否则性能会很糟糕。

收尾

完成了什么?

经验教训

  • TinyPilot 似乎已经耗尽了从博客和 YouTube 评测中获得的营销价值。
  • 自动续订的 TinyPilot 许可证选项是测试经常性收入市场性价比最高的方式。

下个月的目标

  • 尽快把制造转移到代工厂。
  • 为搬出 TinyPilot 的本地办公室制定详细计划。
  • 测试 TinyPilot 许可证的自动续订选项。

求助

  • 如果你有使用第三方 Shopify 经常性订阅应用的经验(无论好坏),尤其是针对数字产品的,请给我发一封电子邮件
  • 如果你能找到我依稀记得的那个 Basecamp 的故事,请在评论中告诉我。

原文由 Michael Lynch 发布

本文章由 stealth/ox-alpha 进行翻译