Skip to main content

Custom CSS/JS and Events

The storefront supports advanced customization via the Custom CSS and Custom JS fields (admin panel → "Storefront Appearance"). This page describes the stable public contract — what you can rely on: these selectors, variables, and window.tirify do not change between releases without notice.

What is stable

Only what is described here should be relied upon: data-tirify-* attributes, CSS variables (tokens), and the window.tirify object (version 1).

Do not rely on internal class names (such as Header-module__abc123) or DOM structure outside of data-tirify-* — these change between releases.


CSS: tokens (theme variables)

Override in Custom CSS. Colors are stored as HSL triplets (H S% L%).

VariablePurpose
--primaryAccent: buttons, links, active navigation
--primary-foregroundText on accent
--backgroundPage background
--foregroundPrimary text
--cardSurfaces: cards, modals
--secondaryTinted surfaces
--muted / --muted-foregroundMuted background / secondary text
--borderBorders
--radiusBase border radius (12px)
:root[data-theme] {
--primary: 20 88% 53%; /* custom orange accent */
--radius: 0.5rem; /* sharper corners */
}

CSS: data-tirify-* selectors

Stable hooks for precise element styling.

AttributeValueWhere
data-tirify-regionheaderheader
data-tirifyblock name (product-card, productsGrid, hero, nav…)corresponding element
data-tirify-pagehome / category / product / accountpage container
data-tirify-product-kinditem / kit / lootbox / variant_pickerproduct card/modal
data-tirify-slugproduct/category slugentity element
data-tirify-productproduct slugproduct card in grid
/* Hide a block */
[data-tirify="hero"] { display: none; }

/* Label for a specific server in the monitoring widget */
[data-monitoringserverid="33049"]::before {
content: "Wipe on Mondays:";
display: block; font-weight: 500;
}

JS: the window.tirify object

In Custom JS, the window.tirify object is available — a read-only snapshot of the storefront state and lifecycle events.

window.tirify = {
version: "1", // contract version
ready: boolean, // true after the store has loaded
getStore(): StoreSnapshot | null, // store snapshot (copy)
getPlayer(): PlayerSnapshot | null, // player snapshot or null (guest)
on(event, callback): () => void, // subscribe; returns an unsubscribe function
off(event, callback): void,
}

Snapshots are copies: mutating them has no effect on the storefront.

StoreSnapshot: slug, name, currency, themeCode, accentColor, supportEnabled, wipeScheduleEnabled, showTopupBonuses, capabilities.

PlayerSnapshot: id, steamId64, displayName, avatarUrl, balance, bonus, joined.

Events

EventWhen firedData (detail)
tirify:readyafter initial store load{ store, player }
tirify:playerplayer login / logout / balance change{ player | null }
tirify:locationchangenavigation to a different storefront section{ path }

You can subscribe in two ways:

// 1) via tirify.on — returns an unsubscribe function
const off = window.tirify.on("player", ({ player }) => {
console.log("Player updated:", player);
});

// 2) via standard addEventListener — data is in e.detail
window.addEventListener("tirify:locationchange", (e) => {
console.log("Section opened:", e.detail.path);
});
tip

on("ready", cb) fires immediately even if the store has already loaded by the time you subscribe — you will never miss the ready event.

Example: player avatar in the header

window.tirify?.on("ready", ({ player }) => {
if (!player) return;
const header = document.querySelector('[data-tirify-region="header"]');
if (!header) return;
const img = document.createElement("img");
img.src = player.avatarUrl ?? "";
img.style.cssText = "width:32px;height:32px;border-radius:50%;";
header.prepend(img);
});

Example: reacting to section changes

window.tirify?.on("locationchange", ({ path }) => {
// e.g. send an event to your analytics
console.log("Navigation:", path);
});

What to avoid

  • Internal CSS-module class names (*-module__*) — they are unstable.
  • DOM structure outside of data-tirify-* hooks.
  • Any window.* other than window.tirify.