MMOLove Docs

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

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-modepopup (default) or modal.
  • data-themelight (default) or dark.
  • data-label — override the button text (default Vote).
  • 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/vote

Vanilla

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.Vote

VoteEmbed.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
}
FieldTypeMeaning
source"mmolove"Discriminator — validated before onVote fires.
type"vote-result"Message type — validated.
serverIdstringMust match the id you opened with — validated.
outcomestringThe vote outcome (e.g. counted, flagged, cooldown).
cooldownUntilnumber?Unix-ms the voter can vote again (on a cooldown).
streaknumber?The voter's current vote streak, when known.
xpnumber?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

On this page