• log out

Assets Badges & Referrals: Gamification and Growth Mechanics on Qbix

The Qbix Platform includes a lightweight but powerful gamification layer consisting of:

  • Badges β€” achievements that users can earn
  • Earned Events β€” timestamped records of earning badges
  • Leaderboards β€” summarized daily points
  • Referrals β€” a companion system awarding points when users invite others

These systems are deeply integrated with Qbix Streams, enabling notifications, subscriptions, and viral growth loops across communities.

Badges: Static Achievement Definitions

Each badge is defined in assets_badge. It belongs to an app and (optionally) a community.

CREATE TABLE assets_badge (
    appId        VARBINARY(31) NOT NULL,
    communityId  VARBINARY(31),
    name         VARCHAR(63) NOT NULL,
    icon         VARBINARY(255),
    title        VARCHAR(255) NOT NULL,
    description  TEXT,
    points       SMALLINT NOT NULL DEFAULT 0,
    PRIMARY KEY (appId, name)
);

A badge’s points value determines its contribution to leaderboards. Example badge definitions:

  • first_post β†’ 5 points
  • event_host β†’ 50 points
  • invited_friend β†’ 10 points

Earned Badges: Event Stream of Achievements

Every time a user earns a badge, Qbix inserts a row into assets_earned:

CREATE TABLE assets_earned (
    appId        VARBINARY(31) NOT NULL,
    communityId  VARBINARY(31),
    earnedTime   TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    userId       VARCHAR(31) NOT NULL,
    badgeName    VARCHAR(255) NOT NULL,
    publisherId  VARBINARY(31),
    streamName   VARBINARY(255),
    KEY byTime   (appId, communityId, earnedTime),
    KEY byUser   (appId, communityId, userId)
);

These rows form the time-series history of user achievements.

Earning a badge

Assets_Earned::badge('abcd1234', 'first_post', [
	'publisherId' => $thread->publisherId,
	'streamName'  => $thread->name,
	'earnedTime'  => time(),
	'duplicate'   => true
]);

If duplicate is false, the system prevents awarding a badge twice.

Computing Totals & Summaries

Use Assets_Badge::badgesAndTotals() to compute point totals from earned badges.

$leaders = Assets_Badge::badgesAndTotals(
	strtotime('-30 days'),
	time(),
	[
		'communityId' => 'JGR'
	]
);

Returns structure:

[
  "userA" => [
      "badges" => [BadgeObj, BadgeObj, ...],
      "total"  => 37
  ],
  "userB" => [
      "badges" => [...],
      "total"  => 24
  ]
]

Leaderboards: Daily Summaries

The daily leaderboard table:

CREATE TABLE assets_leader (
    communityId VARBINARY(31) NOT NULL,
    day         DATE NOT NULL,
    userId      VARCHAR(31) NOT NULL,
    points      SMALLINT NOT NULL DEFAULT 0,
    PRIMARY KEY (communityId, day, userId)
);

A nightly cron job can compute the day's earned badges and store totals:

$today = date('Y-m-d');

$leaders = Assets_Badge::badgesAndTotals(
	strtotime("$today 00:00:00"),
	strtotime("$today 23:59:59")
);

foreach ($leaders as $userId => $info) {
	$row = new Assets_Leader([
		'communityId' => 'JGR',
		'day'         => $today,
		'userId'      => $userId,
		'points'      => $info['total']
	]);
	$row->save(true);
}

Users_Referred: Tracking Referrals & Qualification

The Users_Referred table tracks:

  • which user was invited (userId)
  • who invited them (byUserId)
  • which community or entity they were referred to
  • the points earned for this referral
  • whether the referral reached a qualification threshold

The logic is implemented in Users_Referred::handleReferral().

Referrals table behavior

$r = new Users_Referred([
	'userId'        => $userId,
	'toCommunityId' => $publisherId,
	'byUserId'      => $invitingUserId
]);

If a referral row exists, it updates; otherwise it inserts. Each referral type carries:

  • points β€” for leaderboard scoring
  • qualified β€” threshold after which a referral is considered β€œsuccessful”

Example configuration:

Users/referred/event/points     = 10
Users/referred/event/qualified  = 10

Referral logic

Users_Referred::handleReferral(
	$asUserId,
	$invite->publisherId,
	$s->type,
	$invite->invitingUserId
);

This method:

  1. Loads referral point values from config
  2. Creates or updates the referral record
  3. Tracks when the referral β€œqualifies” (crosses threshold)
  4. Stores cumulative points: max(previous, current)

The max() rule ensures referral points never decrease.

Referrals Triggered from Stream Subscriptions

In Qbix, joining or subscribing to streams via an invite token automatically creates a referral event:

// Inside Streams::subscribe
if ($token = $_SESSION['Streams']['invite']['token']) {
	if ($invite = Streams_Invite::fromToken($token)) {
		foreach ($streamsJoined as $s) {
			Users_Referred::handleReferral(
				$asUserId,
				$invite->publisherId,
				$s->type,
				$invite->invitingUserId
			);
		}
	}
}

This creates a closed loop:

  • A user shares an invite link
  • The invitee joins streams
  • A referral row + points are recorded
  • Badges or leaderboards can pick up these points

Integrating Referrals Into Leaderboards

Referral points live in users_referred and badge points live in assets_earned. Both can contribute to the same leaderboard.

Example daily point total:

$badgeTotals     = Assets_Badge::badgesAndTotals($from, $until);
$referralTotals  = Users_Referred::computeTotals($from, $until); // hypothetical aggregator

$combined = [];

foreach ($badgeTotals as $u => $info) {
	$combined[$u] = $info['total'];
}

foreach ($referralTotals as $u => $pts) {
	$combined[$u] = Q::ifset($combined, $u, 0) + $pts;
}

This creates a unified scoring model mixing achievements + referrals.

Summary of Badge & Referral Architecture

assets_badge      β†’ static definitions (title, points, icon)
assets_earned     β†’ time-series of earned badges
assets_leader     β†’ daily point totals
users_referred    β†’ referral-based points & qualification tracking

Assets_Earned::badge()          β†’ award a badge
Assets_Badge::badgesAndTotals() β†’ compute badge points
Users_Referred::handleReferral()β†’ track referrals
Streams::subscribe()            β†’ triggers referral creation from invite tokens
Cron jobs                        β†’ compute daily leaderboard entries
Streams posts                    β†’ optional achievements/notifications

Together these systems form a cohesive gamification + growth engine for Qbix apps. Badges reward engagement, referrals reward virality, and leaderboards create competition.