Daily retention loop
12-hour vote cooldown is a perfect daily-return cadence. Reward voters with something they actually want and they'll log in every single day to claim it.
Drop the vote button in your game, get notified when a player votes, grant rewards automatically.
Wiring the callback takes ~30 lines of code and unlocks a daily-return mechanic, free organic traffic, and a permanent backlink to your game. Here's why every vibe-coded game should ship it.
12-hour vote cooldown is a perfect daily-return cadence. Reward voters with something they actually want and they'll log in every single day to claim it.
Higher monthly votes → higher rank → more eyeballs on your listing. Players invite friends to vote for them too. Compounds without ad spend.
Your listing carries a do-follow link to your game URL. Free domain authority boost every month you stay listed | indexed by Google within days.
One endpoint. POST + GET. Idempotent on vote_id. No queues, no auth headers, no schemas. Drop the receiver and forget it exists.
Anything your game can grant. The callback fires once per successful vote with a unique vote_id | grant whatever fits your economy. Here are six battle-tested patterns from RSPS & MMO toplists you can copy into your vibe-coded game today.
Drop a flat amount of coins, gems, gold, or credits per vote. Easiest to balance, hardest to abuse | the 12h cooldown caps daily drip at 2 votes per IP.
Example: "+250 gold on every successful vote"
Open a free common-tier crate. Track vote streaks and bump rarity | 7 days straight unlocks an epic roll, 30 days unlocks a legendary.
Example: "Vote-streak chest: rare → epic at 7d → legendary at 30d"
Mint a "Daily Voter's Token" required for a weekly heroic quest. Soft-gated, never blocks the main story | rewards consistent voters with story content.
Example: "+1 Voter's Token per vote → 7 tokens unlock weekly raid"
Time-limited vote-locked cosmetics. Whales can't buy them | the only way in is consistent voting. Drives FOMO without breaking pay-to-win balance.
Example: "This month's voter-only emote: Galaxy Wave"
Accumulate +1 vote point per vote. Spend at a hand-curated rotating shop | mounts, pets, XP scrolls, name-change tokens, exclusive titles.
Example: "30 vote points = Phoenix mount (vote-shop exclusive)"
Vote = +50% XP or +25% gold drops for the next 60 minutes. Turns voting into a pre-grind ritual and keeps the session active long after the vote.
Example: "Vote → 1-hour double-XP buff stack"
All six patterns work with the standard callback below | grant your reward inside the voted=1 branch and de-dupe on vote_id so retries don't double-pay. Mix & match: most established games run currency + a vote store + boosts simultaneously.
Link to this URL from your game's "Vote on VibeTopList" button. The ?ref= parameter is the player's username | round-tripped back to you.
https://vibetoplist.com/vote/<your-listing-slug>?ref=PLAYER_USERNAME
Aliases also accepted: ?u=, ?username=, ?incentive=, ?postback=, ?id=. Any of them works.
After every successful vote, VibeTopList fires both a POST and a GET to your configured callback URL with these parameters:
secret | Your callback secret (verify this!) |
|---|---|
voted | 1 on success, 0 if rejected post-validation |
userip | Voter's IP (for your own anti-abuse) |
userid | The ref parameter you passed in (the player username) |
reset | Unix timestamp when the same IP can vote again |
vote_id | VibeTopList's internal vote id (use for idempotent reward grants) |
We don't validate your response | fire-and-forget. Return any 2xx and we'll log it as success.
<?php
$secret = "YOUR_CALLBACK_SECRET";
if (($_REQUEST['secret'] ?? '') !== $secret) { http_response_code(403); exit; }
if (($_REQUEST['voted'] ?? '0') === '1') {
$player = $_REQUEST['userid'] ?? '';
$vote_id = $_REQUEST['vote_id'] ?? '';
// grant reward to $player, idempotent on $vote_id
}
http_response_code(200);
app.all('/vote-callback', (req, res) => {
const p = { ...req.query, ...req.body };
if (p.secret !== process.env.VTL_SECRET) return res.status(403).end();
if (p.voted === '1') {
grantReward(p.userid, p.vote_id);
}
res.json({ ok: true });
});
@app.route('/vote-callback', methods=['GET', 'POST'])
def vote_callback():
p = {**request.args, **request.form}
if p.get('secret') != app.config['VTL_SECRET']:
abort(403)
if p.get('voted') == '1':
grant_reward(p.get('userid'), p.get('vote_id'))
return 'ok'
If you can't accept incoming requests, poll us instead.
GET https://vibetoplist.com/api/v1/check-vote?key=YOUR_API_KEY&username=PLAYER
→ {"voted": true, "voted_at": "2026-05-09T13:42:11Z",
"vote_id": 42, "claimed": false}
Mark a vote as rewarded so you don't double-grant on retries.
POST https://vibetoplist.com/api/v1/claim-vote
Content-Type: application/json
{"key": "YOUR_API_KEY", "vote_id": 42}
→ 200 {"ok": true, "claimed_at": "..."}
→ 409 {"error": "already_claimed"}
Embed live vote counts on your own site.
GET https://vibetoplist.com/api/v1/listing/<your-slug>
→ {"slug": "...", "name": "...", "rank": 5, "votes_this_month": 1432, ...}
Where do I find my API key and callback secret? → Dashboard → your listing → API & Callbacks.