Vote button
Embed a click-to-vote button on your own site or launcher. Players vote for your server in a popup or in-app modal without leaving your page — via a script tag, the @mmolove/vote npm package, or the MMOLove.Vote ASP.NET helper.
The vote button lets players vote for your server from your own site or launcher — no trip to MMOLove required. A click opens the mmolove-hosted vote widget as a popup (default) or an in-app modal, the player votes, and your page gets the result back via a callback.
The vote itself never runs on your origin: Cloudflare Turnstile, fingerprinting, and the 1-vote-per-identity-per-day rule all stay under MMOLove's control inside the widget. Your page only ever sees a validated result message — never the vote mechanics — so embedding can't weaken anti-fraud, and counts can't be inflated (dedup is per-person, not per-site).
The easiest way to grab the snippet is the Embed vote button card on your server's dashboard (Integration tab): toggle popup/modal and light/dark, preview it live, and copy a ready-made tag. This page documents the three integration paths.
Three ways to embed
Script tag
One line, no build step. The hosted embed.js renders the button for you.
npm — @mmolove/vote
Typed TS/ESM + a React component. Open the widget from your own JS.
.NET — MMOLove.Vote
Server-side ASP.NET / Blazor helper that emits the snippet.
Your serverId is the MMOLove server id — it's in your dashboard URL and on the
Integration tab. mode is popup (default) or modal; theme is light
(default) or dark. The canonical origin is https://mmolove.gg.
Script tag
The zero-dependency path: drop in the hosted loader and it renders the badge-fused "Vote →" button, opens the widget on click, and closes it on success.
<script
src="https://mmolove.gg/embed.js"
data-mmolove-vote="<serverId>"
data-mode="popup"
data-theme="light"
async
></script>data-mmolove-vote— your server id (required).data-mode—popup(default) ormodal.data-theme—light(default) ordark.data-label— override the button text (defaultVote).data-on-vote— the name of a global function to call with the result.
The loader also exposes an imperative API for custom triggers:
<button id="vote">Vote for us</button>
<script src="https://mmolove.gg/embed.js" async></script>
<script>
document.getElementById("vote").addEventListener("click", () => {
window.MMOLoveVote.open({
serverId: "<serverId>",
mode: "modal",
theme: "dark",
onVote: (result) => console.log("outcome:", result.outcome),
});
});
</script>npm — @mmolove/vote
A tiny, dependency-free TypeScript/ESM package for when you'd rather open the widget from your own bundled JS (and get types for the result).
npm i @mmolove/voteVanilla
import { openVote, mountVoteButton } from "@mmolove/vote";
// Open the widget imperatively (e.g. from your own button):
openVote({
serverId: "<serverId>",
mode: "popup", // "popup" (default) | "modal"
theme: "dark", // "light" (default) | "dark"
onVote: (result) => console.log(result.outcome),
});
// Or render a ready-made "Vote →" button into an element:
const unmount = mountVoteButton(document.getElementById("vote")!, {
serverId: "<serverId>",
mode: "modal",
});
// later: unmount();React
The React component lives in a separate entry (@mmolove/vote/react) so the
core works with no React dependency — React is an optional peer.
import { VoteButton } from "@mmolove/vote/react";
<VoteButton
serverId="<serverId>"
mode="modal"
theme="dark"
className="my-vote-btn"
onVote={(r) => console.log(r.outcome)}
>
Vote for us →
</VoteButton>;origin defaults to https://mmolove.gg on every entry; override it for staging /
self-host.
.NET — MMOLove.Vote
A server-side ASP.NET / Blazor helper that emits the embed snippet — the same
<script src=".../embed.js"> as above, rendered from your server.
dotnet add package MMOLove.VoteVoteEmbed.Script(...) returns an IHtmlContent, so Razor renders it directly
(attribute values are HTML-encoded):
// In a .cshtml Razor view:
@using MMOLove.Vote
@VoteEmbed.Script("<serverId>", mode: "modal", theme: "dark")Or register the helpers once in _ViewImports.cshtml and use the TagHelper:
// _ViewImports.cshtml
@addTagHelper *, MMOLove.Vote<mmolove-vote server-id="<serverId>" mode="modal" theme="dark" />Both render the identical snippet. origin defaults to https://mmolove.gg.
No-script fallback
The most minimal embed possible — a plain link that opens the widget in a new tab.
No JavaScript, no result callback, but it always works (great for forums, emails,
or as a <noscript> fallback):
<a href="https://mmolove.gg/embed/vote/<serverId>" target="_blank" rel="noopener">
Vote on MMOLove
</a>The result payload
When a vote resolves, the widget posts a message back to your page. The script
loader and the npm package both validate it (source === "mmolove",
type === "vote-result", and a matching serverId) before invoking your onVote
callback:
{
"source": "mmolove",
"type": "vote-result",
"serverId": "<serverId>",
"outcome": "counted",
"cooldownUntil": 1733600000000,
"streak": 7,
"xp": 50
}| Field | Type | Meaning |
|---|---|---|
source | "mmolove" | Discriminator — validated before onVote fires. |
type | "vote-result" | Message type — validated. |
serverId | string | Must match the id you opened with — validated. |
outcome | string | The vote outcome (e.g. counted, flagged, cooldown). |
cooldownUntil | number? | Unix-ms the voter can vote again (on a cooldown). |
streak | number? | The voter's current vote streak, when known. |
xp | number? | XP awarded / total, when known. |
The onVote result is a UX hook (close the surface, show a thank-you), not a
reward trigger. To grant in-game rewards when a player votes, use the signed
reward callback — that's the server-to-server path with
HMAC verification.
See also
All languages at a glance
A concise side-by-side of the referral flow across PHP, Node/JS, Python, .NET/C#, and cURL — pick your stack, then jump to the full SDK guide.
Vote badge
Embed the live "Ranked on MMOLove" vote badge — a self-updating SVG showing your hearts and rank, wrapped in an attributed backlink.