插件商业化与变现
Obsidian 插件生态支持多种商业化模式。本文介绍如何将插件开发转化为可持续收入来源,同时遵守 Obsidian 社区规范。
商业化前置条件
技术基础
法律准备
| 准备项 | 说明 |
|---|---|
| 开源许可证 | 选择 MIT / GPL / Apache 等开源协议 |
| 隐私政策 | 如收集用户数据,需提供隐私政策 |
| 服务条款 | 如提供云端服务,需制定 ToS |
| 商标检查 | 确认插件名称不侵犯他人商标 |
| 税务了解 | 了解个人开发者税务申报要求 |
Obsidian 插件变现模式
模式 1:完全免费 + 赞助
适合:小工具、个人项目
插件 → 完全免费
变现渠道:
- GitHub Sponsors
- 爱发电(国内)
- PayPal / Ko-fi优点:简单、无争议、用户基数大 缺点:收入不稳定、依赖用户自愿
模式 2:开源 + 付费支持
适合:中大型工具插件
核心功能 → 开源免费
高级功能 → 付费解锁(许可证密钥)实现方式:
- 核心代码开源在 GitHub
- 高级功能通过 License Key 解锁
- 用户在官网/平台购买许可证
- 许可证验证通过 API 实现
模式 3:免费 + 云服务付费
适合:需要后端服务的插件
本地功能 → 免费
云端功能(同步、AI、存储)→ 按量/按月付费示例:
- 本地笔记搜索免费
- 云端全文搜索/AI 问答付费
- 免费版限制每月 API 调用次数
模式 4:免费版 + 付费版(Freemium)
适合:功能丰富的综合插件
免费版:
- 基础功能
- 限制笔记数量
- 限制使用频率
Pro 版(月费/年费):
- 全部功能
- 无限制使用
- 优先技术支持模式 5:一次性买断
适合:工具型插件、无持续维护成本
插件 → 一次性付费 $X
- 终身使用
- 包含未来更新
- 无订阅压力定价策略
参考定价
| 插件类型 | 免费版 | 付费版 | 年费参考 |
|---|---|---|---|
| 小工具 | 完全免费 | — | — |
| 效率工具 | 基础功能 | $5-15 | $3-10 |
| AI 插件 | 有限次数 | $8-20 | $5-15 |
| 同步工具 | 试用 30 天 | $15-30 | $10-25 |
| 开发工具 | 基础功能 | $10-25 | $8-20 |
定价建议
- 研究竞品:查看类似插件的定价
- 价值导向:基于用户获得的效率提升定价
- 分层定价:提供个人版/团队版/企业版
- 试用期:提供 14-30 天免费试用
- 早鸟优惠:发布初期提供折扣
技术实现
许可证验证
typescript
import { PluginSettingTab, App, Setting, request } from "obsidian";
interface LicenseSettings {
licenseKey: string;
isValid: boolean;
plan: "free" | "pro";
expiresAt: string | null;
}
export class LicenseManager {
private settings: LicenseSettings;
async validateLicense(key: string): Promise<boolean> {
try {
const response = await request({
url: "https://api.yourplugin.com/validate",
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ key }),
});
const data = JSON.parse(response);
this.settings.licenseKey = key;
this.settings.isValid = data.valid;
this.settings.plan = data.plan;
this.settings.expiresAt = data.expiresAt;
return data.valid;
} catch (error) {
console.error("License validation failed:", error);
return false;
}
}
isPro(): boolean {
return this.settings.plan === "pro" && this.settings.isValid;
}
isExpired(): boolean {
if (!this.settings.expiresAt) return false;
return new Date(this.settings.expiresAt) < new Date();
}
}功能门控
typescript
class FeatureGate {
private licenseManager: LicenseManager;
isFeatureAvailable(feature: string): boolean {
const freeFeatures = ["basic-search", "basic-export"];
const proFeatures = ["ai-assist", "batch-process", "cloud-sync"];
if (freeFeatures.includes(feature)) {
return true;
}
if (proFeatures.includes(feature)) {
return this.licenseManager.isPro() && !this.licenseManager.isExpired();
}
return false;
}
// 在命令注册时检查
registerCommand(plugin: Plugin, feature: string, callback: () => void) {
plugin.addCommand({
id: `feature-${feature}`,
name: this.getFeatureName(feature),
checkCallback: () => {
if (this.isFeatureAvailable(feature)) {
callback();
return true;
}
// 显示升级提示
new Notice("此功能需要 Pro 版本,点击升级");
return false;
},
});
}
}设置面板中的许可证管理
typescript
export class ProSettingsTab extends PluginSettingTab {
display(): void {
this.containerEl.empty();
// 许可证状态
new Setting(this.containerEl)
.setName("许可证状态")
.setHeading();
new Setting(this.containerEl)
.setName("当前计划")
.setDesc(this.licenseManager.isPro() ? "Pro 版" : "免费版")
.addText((text) => {
text.setValue(
this.licenseManager.isExpired() ? "已过期" : "有效"
);
text.inputEl.disabled = true;
});
new Setting(this.containerEl)
.setName("许可证密钥")
.setDesc("输入许可证密钥解锁 Pro 功能")
.addText((text) => {
text.setPlaceholder("XXXX-XXXX-XXXX-XXXX");
text.setValue(this.licenseManager.settings.licenseKey);
text.inputEl.style.width = "250px";
})
.addButton((btn) => {
btn.setButtonText("验证");
btn.onClick(async () => {
btn.setButtonText("验证中...");
const input = this.containerEl.querySelector(
'input[type="text"]'
) as HTMLInputElement;
const valid = await this.licenseManager.validateLicense(
input.value
);
if (valid) {
new Notice("许可证验证成功!Pro 功能已解锁");
this.display(); // 刷新界面
} else {
new Notice("许可证无效,请检查密钥");
}
});
});
// 升级链接
new Setting(this.containerEl)
.setName("升级到 Pro")
.setDesc("解锁全部高级功能")
.addButton((btn) => {
btn.setButtonText("前往购买");
btn.onClick(() => {
window.open("https://yourplugin.com/pricing", "_blank");
});
});
}
}支付平台选择
| 平台 | 手续费 | 适合 | 优势 |
|---|---|---|---|
| Gumroad | 10% | 国际市场 | 简单易用、支持订阅 |
| Lemon Squeezy | 5%+50¢ | 国际 SaaS | 支持许可证密钥管理 |
| Paddle | 5%+50¢ | 国际企业 | 完善的税务处理 |
| 爱发电 | 5% | 国内市场 | 微信/支付宝支付 |
| 自建 Stripe | 2.9%+30¢ | 有开发能力 | 最低费率、最大灵活 |
合规要求
Obsidian 社区规范
- 不得强制付费:社区插件市场中的插件必须有可用的免费基础功能
- 清晰标注:插件描述中需说明付费功能
- 数据安全:不得在未经用户同意的情况下收集或传输数据
- 开源要求:提交到社区市场的插件必须开源
- 不得植入广告:插件中不得包含广告
隐私合规
typescript
// 隐私政策示例
export const PRIVACY_POLICY = `
## 隐私政策
### 我们收集什么数据
- 许可证密钥(用于验证)
- 使用统计(匿名,可选)
### 数据如何使用
- 验证许可证有效性
- 改进产品功能
### 数据存储
- 许可证密钥存储在本地 Obsidian 配置中
- 使用统计数据通过 HTTPS 加密传输
### 第三方服务
- 支付处理:[平台名称]
- 不使用任何第三方分析服务
### 用户权利
- 您可以随时导出或删除您的数据
- 联系:privacy@yourplugin.com
`;用户支持
建立支持渠道
| 渠道 | 用途 | 推荐工具 |
|---|---|---|
| 文档站 | 使用文档 | GitBook / VitePress |
| FAQ | 常见问题 | GitHub Discussions |
| Bug 反馈 | 问题报告 | GitHub Issues |
| 功能请求 | 用户反馈 | GitHub Issues / Featurebase |
| 社区交流 | 用户互助 | Discord / QQ群 |
| 邮件支持 | 付费用户 | 优先级邮箱 |
版本管理
typescript
// 插件版本管理
const VERSION_INFO = {
current: "1.2.0",
minObsidian: "1.5.0",
changelog: {
"1.2.0": {
features: ["新增 AI 辅助功能", "支持自定义主题"],
fixes: ["修复导入大文件崩溃问题"],
breaking: ["配置格式变更,需重新设置"],
},
"1.1.0": {
features: ["新增批量导出功能"],
fixes: ["修复 macOS 快捷键冲突"],
},
},
};
// 检查更新
async function checkUpdate(): Promise<void> {
const response = await request({
url: "https://api.github.com/repos/yourname/your-plugin/releases/latest",
});
const release = JSON.parse(response);
if (release.tag_name > VERSION_INFO.current) {
new Notice(
`发现新版本 ${release.tag_name},请前往设置更新`
);
}
}增长策略
1. 内容营销
- 撰写插件使用教程博客
- 制作视频教程发布到 YouTube/B站
- 在 Obsidian 论坛分享使用案例
- 参与社区讨论,自然推荐插件
2. 用户留存
- 定期发布更新和新功能
- 收集用户反馈并快速响应
- 提供迁移指南(从竞品迁移)
- 建立 Beta 测试社区
3. 扩展生态
- 提供 API 供其他插件集成
- 与互补插件合作推广
- 支持主题开发者适配
- 建立模板/配置市场