UGC Reactions from Real Creators
Real creator library videos at $11 and images at $8. Custom production from $25/video with a $250 minimum. Commercial licensing included.
翻訳待ち
Free, self-hosted URL shortener on Cloudflare Workers + D1: geo/device routing, A/B tests, QR codes, app deep links, real-time analytics, plus GA4 / Search Console / Bing site & SEO insights. 免费开源、可自托管的短链与站点分析
翻訳待ち
Loading the full README.
Read the full README ↗utm_content=ab-a / ab-b,在 GA4 里对比转化。?src= 的链接,即使对方不发送 Referer 也能分清来源。同时支持 utm_source / utm_campaign。bl•••.com,方便截图分享。?src= / Referer)统计每个站点带来的短链点击、独立访客和点出率;也能看每个短链跳转到哪些站点。可选的转化追踪给跳转加上 utm 参数,在 GA4 里看到每个短链的到站会话和关键事件。概览:访问趋势、实时访问、来源和热门短链
短链详情:跳转规则、二维码和访问分析
跳转规则:按国家 / 地区、设备分流,A/B 测试
站点详情:GA4、Search Console、Bing 数据和优化建议
演示数据,均为虚构
点击上方 Deploy to Cloudflare 按钮,按提示授权即可自动创建 Worker 和 D1 数据库。部署完成后访问 https://<worker 地址>/admin,用默认密码 admin 登录,按提示设置新密码即可。
部署后的默认地址是
*.workers.dev,在中国大陆通常打不开。面向国内访客请先绑定自己的域名,之后复制的短链和二维码都用新域名。
需要 Node.js 18+ 和一个 Cloudflare 账号。
git clone https://github.com/ccvar/cligc_link.git
cd cligc_link
npm install
# 登录 Cloudflare
npx wrangler login
# 创建 D1 数据库,把输出的 database_id 填到 wrangler.toml
npx wrangler d1 create cligc-link
# 部署
npx wrangler deploy
部署后访问 https://<worker 地址>/admin,用默认密码 admin 登录。首次登录会要求设置新密码,设置前后台其他功能都不可用,设置后默认密码立即失效。
部署后请尽快登录并修改密码。也可以在部署前用
npx wrangler secret put ADMIN_PASSWORD直接指定初始密码,这样就不会出现默认密码。
域名需要托管在 Cloudflare。在 wrangler.toml 中添加:
routes = [
{ pattern = "go.example.com", custom_domain = true },
]
重新执行 npx wrangler deploy 即可。
用一键部署的:在 Cloudflare 控制台打开 Workers 和 Pages → 你的 Worker → 设置 → 域和路由 → 添加 → 自定义域,填入域名即可(同样要求域名托管在 Cloudflare)。之后用新域名打开后台,复制的短链和二维码就会用新域名。
每个版本都会打 vX.Y.Z 标签、在 Releases 里写明更新内容(也见 CHANGELOG.md)。后台“设置 → 系统状态”显示当前版本;定时任务每天到 GitHub 查一次最新版本(只读取版本号,不上报任何数据),有新版本时在系统状态里提示,并推送一次到已开启的 Telegram / 邮箱。
数据库不需要手动迁移:新版本第一次运行时会自动补表、补列,数据不会丢失。升级后出问题,可以用 npx wrangler rollback 回到上一次部署的代码。
命令行部署的:在项目目录执行
npm run upgrade
它会拉取最新发布的版本、保留你在 wrangler.toml 里的 Worker 名称、域名、D1 数据库和 [vars]、安装依赖,确认后部署。只想先更新代码、检查后再部署:npm run upgrade -- --no-deploy;升级到指定版本:npm run upgrade -- --to v1.2.0。
用“Deploy to Cloudflare”按钮部署的:按钮会在你的 GitHub 下生成一个仓库,并让 Cloudflare 在仓库有新提交时自动部署。打开这个仓库的 Actions → 同步上游新版本 → Run workflow,它会把最新版本合并进你的仓库(同样保留 wrangler.toml 里的配置),Cloudflare 随后自动重新部署。默认只在你手动运行时升级;想每周一自动升级,把 .github/workflows/sync-upstream.yml 里 schedule 那两行前面的 # 去掉(自动部署的新代码能访问你保存的 Google / Bing 凭据,所以默认不开)。
在 v1.1.0 之前部署的,仓库里还没有升级脚本:命令行部署的先
git pull一次(wrangler.toml有冲突时保留自己的数据库 ID 和域名),之后就可以用npm run upgrade;一键部署的把本仓库的scripts/和.github/workflows/sync-upstream.yml复制到自己的仓库,再运行上面的 Action。
变量(写在 wrangler.toml 的 [vars] 中):
| 名称 | 说明 |
|---|---|
HOME_URL | 访问根路径 / 时跳转到的地址;留空则显示内置的产品首页。填了的话还要去掉 [assets] 里 run_worker_first 前面的 #(首页平时是静态文件,不经过 Worker) |
ADMIN_HOST | 后台只允许通过这个域名访问;留空则任意域名的 /admin 都可访问 |
TURNSTILE_SITEKEY | Cloudflare Turnstile 站点密钥;留空则登录不做人机验证 |
密钥(用 npx wrangler secret put <名称> 设置):
| 名称 | 必填 | 说明 |
|---|---|---|
ADMIN_PASSWORD | 否 | 初始后台密码。不设置时默认为 admin,首次登录强制修改 |
SESSION_SECRET | 建议 | 会话签名密钥,也用于加密保存在数据库里的令牌和客户端密钥。不设置时首次运行自动生成并保存在数据库中(这时数据库被导出或泄露,加密的内容也能被解开);更换后需要在后台重新填写客户端信息、重新连接 Google |
TURNSTILE_SECRET | 否 | Turnstile 服务端密钥,与 TURNSTILE_SITEKEY 配套 |
没设置 SESSION_SECRET 时,会话密钥自动生成并存在数据库里;它也用来加密数据库里的 Google 令牌、客户端密钥和 Cloudflare 令牌,所以数据库一旦泄露,这些也能被解开。把同一个值改存成 Wrangler Secret,登录状态、已连接的 Google 账号都不受影响:
在项目目录里执行(<数据库名> 是 wrangler.toml 里的 database_name,默认 cligc-link):
# 1. 读出数据库里的密钥,直接通过管道存成 Secret(不会显示在屏幕上)
npx wrangler d1 execute <数据库名> --remote --json \
--command "SELECT value FROM settings WHERE key = 'session_secret'" \
| node -e "let s='';process.stdin.on('data',(d)=>s+=d).on('end',()=>process.stdout.write(JSON.parse(s)[0].results[0].value))" \
| npx wrangler secret put SESSION_SECRET
# 2. 确认后台还能正常使用后,删掉数据库里的副本
npx wrangler d1 execute <数据库名> --remote --command "DELETE FROM settings WHERE key = 'session_secret'"
用一键部署、本地没有项目的:在 Cloudflare 控制台打开 存储和数据库 → D1 → 你的数据库 → 控制台,执行 SELECT value FROM settings WHERE key = 'session_secret' 并复制结果;再打开 Workers 和 Pages → 你的 Worker → 设置 → 变量和机密 → 添加,类型选“密钥”,名称填 SESSION_SECRET,值粘贴刚才复制的内容并部署。确认后台正常后,回到 D1 控制台执行 DELETE FROM settings WHERE key = 'session_secret'。
This is the beginning of the README. Read the rest at the original. Read the full README ↗