Trackers
Collect posts, YouTube Shorts, TikTok videos, Discord and Telegram activity, and your own events, so quests can reward them.
A tracker watches for activity outside Domino and keeps a record of it, so your quests can reward it. For example:
- Posts on X that mention your launch hashtag.
- Messages and reactions in your Discord server.
- Messages and reactions in your Telegram group.
- YouTube Shorts your members post on their own channels.
- TikTok videos your members post on their own accounts.
- Token balances in the wallets your members linked, sampled once a day.
- On-chain events or game results your own server sends in.
Collecting is the tracker's only job. It keeps what it finds in a dataset for one project and environment, separate from members, quests and rewards. A quest then decides what counts and who earns what.
What members see
Members don't interact with a tracker directly. They link their X, Discord or Telegram account, their YouTube channel or TikTok account, or their wallet, and take part as usual: post, react, play. When a quest rewards that activity, they see the quest complete. When it doesn't, your app can show them why, such as "No member has linked this X account", and for some quests they can claim activity from before they linked.
Domino only ever matches activity to a member through an account they proved they own. A username or a verification badge is never enough.
Words on this page
| Term | Meaning |
|---|---|
| Tracker | A published definition: a stable key, a source, and a collection window. |
| Dataset | The records a tracker has collected. |
| Record | One collected item, such as an X post, a Discord reaction, or a chain event, with occurrence, first-seen, and observation times. |
| Record data | The JSON object a record carries: the provider's post for X, a fixed shape for Discord, and for a custom source the shape its schema declares. A record stored before the schema changed that no longer matches it never reaches a quest as typed data. |
| Content revision | The stable body of an X post: text, media, references, and author ID. |
| Observation | One sample of a record at one time: its data, accounts, and removal status, and for an X post its engagement counters and author profile and verification. |
Sources
| Source | Who collects |
|---|---|
| X search | Domino polls the search on a schedule and refreshes posts it already knows during their first week. The X credential stays with the platform. |
| Discord messages, Discord reactions | Domino's Discord gateway records each new message or reaction in the server connected to the project, as it happens. It keeps a record only when one of its accounts is a Discord account a member of the project has linked. Message edits update text when the tracker keeps it. Message deletes remove the record and erase its text. |
| Telegram messages | Domino's Telegram bot records each message a person posts in the groups connected to the project, as it happens, without its text. It keeps a record only when the poster is a Telegram account a member of the project has linked. Bots', service and channel messages are never recorded, and a deleted message stays recorded. |
| Telegram reactions | Domino's Telegram bot records each reaction added in the groups connected to the project, as it happens. It keeps a record only when one of its accounts is a Telegram account a member of the project has linked. A removed reaction removes the record. |
| YouTube Shorts | Domino reads the Shorts on each YouTube channel a member of the project linked as a creator account, with that member's permission, on a schedule. It finds new Shorts and refreshes the views, likes and comments of the ones it knows. A Short that is deleted or made private is removed. A channel that is unlinked is no longer read; its records stay. |
| TikTok videos | Domino reads the public videos on each TikTok account a member of the project linked as a creator account, on a schedule, only ever with that member's own permission. It finds new videos and refreshes the views, likes, comments and shares of the ones it knows. A video the account no longer returns, for example because it was deleted, is removed. An account that is unlinked, or whose access needs reconnecting, is not read; its records stay. |
| Wallet balances | Domino reads the balance of one token in every wallet linked by a member who joined the project, once per project-calendar day, at a time only Domino knows, every wallet at one block on EVM and Cosmos chains (on Solana, every read reaches at least the slot the sample started at). Each wallet is one record, and each day's sample is a new observation of it. A day whose reads all fail has no sample: Domino never records a balance it didn't read. An unlinked wallet is no longer read; its records stay. |
| Custom source | Your server or indexer sends records in. It owns decoding and finality, including blockchain reorganizations. The source declares the shape of its records, and Domino refuses a batch with a record that does not match it, naming the record and the field. |
Collecting is not qualifying
- Every match is kept. An X or custom tracker keeps unverified authors and people who have not joined your project. Apply filters, such as
verifiedormember, when you read. Discord, Telegram, YouTube, TikTok and wallet balance trackers are the exception: they keep only activity that involves a member's linked account. - A tracker has no reward policy. Collecting never awards anything. A quest that declares a tracker trigger evaluates the record observations it selects for the member behind one of the record's accounts.
- Each rule decides. Quests and engagement rules read the dataset, and each can qualify the same post differently.
- Quests read a fixed moment. When a quest checks a tracker, it sees the records as of when the activity happened, and a retry sees the same answer. See maintained tracker datasets for how those reads are captured.
Attribution
Each record says who took part, in roles: who wrote the post, who it replied to, who reacted. Domino pays the member behind one of those accounts, and only when that member has linked and verified the account. The tables below list the roles and account kinds each source has.
| Source | Roles | Account kinds |
|---|---|---|
| X search | author (who wrote the post), inReplyTo (whose post it replies to), quoted (whose post it quotes) and reposted (whose post it reposts), from the captured post | Stable X user IDs |
| Discord messages | author (who posted the message) | Stable Discord user IDs |
| Discord reactions | author (who reacted) and messageAuthor (who wrote the message), when Discord names the message's author | Stable Discord user IDs |
| Telegram messages | author (who posted) | Numeric Telegram user IDs |
| Telegram reactions | author (who reacted) and messageAuthor (who wrote the message), when the bot saw the message | Numeric Telegram user IDs |
| Wallet balances | author (the sampled wallet) | CAIP-10 wallet accounts on the sampled chain |
Custom source with identities | author, plus the named accounts the source declares in accounts, such as recipient | The declared identity kinds |
Custom source without identities | None: the author is an ID your code chooses, attributed to nobody | — |
| Identity kind | Account ID | Attributed to |
|---|---|---|
wallet | A canonical CAIP-10 account ID, such as cosmos:cosmoshub-4:cosmos1… | The member who currently links that wallet in the project |
x | A stable numeric X user ID | The member whose selected, verified X account has that ID |
discord | A stable numeric Discord user ID | The member whose selected, verified Discord account has that ID |
member | A Domino member ID | That member, unless it was erased: then no one |
app:<name> | Your app's own user ID, such as a Telegram or game account ID | The member your app login integration of that kind signed in with that ID in the project |
Tracker triggers
A quest can turn each new record into a chance to earn: every new post with your hashtag, every reaction to your announcement, every game your server reports. You choose which records count, who gets paid, whether members must join the quest first, and what happens to activity from before a member linked their account.
In code, a quest with automatic({ tracker }) turns tracker records into attempts. These choices compose it:
| Choice | Options |
|---|---|
on: which observations fire | "new-record": a record's first observation in this tracker (the default for X and Discord trackers). "new-observation": every observation that becomes a record's current one (the default for custom trackers, which in SDK 1.x include Telegram, YouTube Shorts, TikTok and wallet balance trackers: each refresh or daily sample fires again unless you set on). "data-changed": a new record, or a current observation whose data differs from the previous one. |
where: which data qualifies | Optional. A condition on a path in the record's data, or a list that must all hold: equals a string, number, or boolean, or compare a number or an integer string with gt, gte, lt, and lte. A bound can name one of the quest's integer settings. Paths and values are checked against the tracker's record data. |
beneficiary: who it pays | The record account whose member the attempt belongs to: "author" (the default), "inReplyTo", "quoted" or "reposted" on an X tracker, "messageAuthor" on a Discord reactions tracker, or a named account of a custom record. |
enrollment: who takes part | "none" (the default): every member who has joined the project. "required": only members who enrolled in the quest. |
since: the earliest activity counted | "activation" (the default): records that occurred since the quest was published or last unarchived. "window": every record in the tracker's window. "enrollment", with required enrollment: records that occurred since the member enrolled. |
historical: who releases historical activity | "staff" (the default): only a reviewer's retry. "claim": also the member, who claims it. "automatic": Domino admits it like any other activity. |
- Firing and filtering are not decisions. An observation the mode or filter does not select records nothing and costs no attempt. Older observations only add history.
- Every decision is recorded. Each selected observation gets exactly one trigger outcome: an admission, or a skip with a stable
code, such asunlinked-account, and areasonfor people, such as "No member has linked this X account". Aonce()quest the member already completed recordsalready-completed. Operators see outcomes in Console and through the management API; members read their own withrelay.quests.outcomes(). - A record never pays its author's member through another role. When the beneficiary account is the record's author account, such as a reply to one's own post or a reaction to one's own message, or both accounts belong to the same member, the observation is skipped.
- A skip waits for the event that clears it. Domino decides a skip again, under the quest's current rules, only when the member event that clears its code happens: linking the account clears
unlinked-account, removing a conflicting link clearsambiguous-account, joining the project clearsnot-joined, and enrolling in the quest, or in its campaign, clearsnot-enrolled. Every other skip is final unless staff withreviewpermission retry it. A banned member's records are skipped withmember-banned, which is never decided again: an unban counts only what they do afterwards, and Console's trigger outcomes say there is nothing to do. - Activity is never backfilled by publishing. With the default
since, observations that occurred before the quest was published are skipped. - X posts pay approved creators. X does not allow apps that reward users for posting, so a quest that pays an X post's author, with
automatic({ tracker })orcontent({ tracker }), needs aninGroup(group)prerequisite naming a group of creators the operator approves. Posts by anyone else are skipped withprerequisites-incomplete. A deployment that publishes such a quest without the prerequisite warns withx-post-rewards-ungated. - The attempt keeps what it saw. Once a record starts an attempt, later updates or the member unlinking the account don't change it. Quest code cannot redirect who it pays. See tracker triggers for what the evaluator receives.
Historical activity
Activity from before a member joined in is historical: by default it doesn't pay automatically, so linking an old account can't sweep up months of past posts.
Activity is historical when it occurred before the member linked the account it pays, or before the member enrolled. A link time Domino does not know, such as a Discord connection made before selections existed, counts as later than the activity. Accounts of kind member are never historical: the server that ingests the record vouches for the member.
A linked account or an enrollment decides earlier skips again, and historical activity then becomes a historical skip that names the member. The quest's historical policy says who releases it:
| Policy | What happens to historical activity |
|---|---|
"staff" | It stays skipped until a reviewer retries it. |
"claim" | The member can claim it with relay.quests.claim(). Their outcome is claimable. |
"automatic" | It is admitted, including when the member links the account or enrolls later. |
A retry or claim releases only historical activity: every other rule still applies. Activity that occurred before the member completed a prerequisite never counts.
Revisions and observations
Domino keeps history rather than overwriting a record. An edit to a post's body creates a new content revision. A refreshed like count or author profile creates a new observation with the same revision. Returning to an earlier body reuses that body's revision.
Trackers in the same project and environment that collect the same X post share its latest facts. Each tracker keeps its own matches and first-seen times, so another tracker's discovery never adds a match to yours.
Coverage and changes
- Complete coverage is not a census. It means a collection cycle exhausted the provider's results and refreshed known posts. It does not prove the dataset holds every matching post.
- Changes do not backfill. Changing a query or window keeps collected records and discovers new posts from publication time. Use a new tracker key for a deliberate historical collection: its first publish searches from
window.start, even when that is in the past, as far as the provider's history reaches. - Each cycle searches the whole window. An X tracker searches from its discovery start to now, or to
window.endonce that has passed, on every cycle, up tomaxPagessearch pages. A long, busy window can reach that limit every cycle and reportpartialcoverage with a page-limit warning. - Removal keeps data and collection. Removing a definition from the manifest does not delete its dataset, and it does not stop collection: a deployment publishes only the trackers it lists and leaves the others as they are. Pause or archive a tracker to stop collecting. Pausing stops collection without freezing shared post facts.
- Code or data owns each key. A tracker is code, published by a deployment from
defineTracker, or data: a tracker of a source Domino collects itself, such as an X search or Discord reactions, created in Console or withmanagement.trackers.create. Only its owner changes the definition, and a deployment never changes or removes a data tracker. Data trackers are created and changed in test, and a promotion carries them to live, still owned by data. A promotion never copies the Discord server or Telegram chats a tracker reads; live connects its own. See Create a tracker without a deployment. - Test first. The CLI publishes trackers to test only. A promotion carries them to live once a person with publish permission approves it in Console.
Where next
Define, preview, publish, and read a tracker.
Messages and reactions as tracker records.
Qualify tracked posts and reward their engagement.
How evaluations become completions.
An external score, such as a tracked balance, gets its own ledger.
Tracker-scoped ingestion keys
A personal ingestion key can carry a list of allowed custom tracker IDs. It still belongs to one project and environment, and its owner must still hold ingestion permission. The restriction applies to writes, not reads or other permissions on the same key. Choose only Ingest for an indexer that should not read project data. Existing keys without a tracker restriction keep project-wide ingestion. Operators can inspect, edit or revoke their own keys in Console Settings → API keys. See custom source ingestion.
Read and feed trackers from the CLI
domino trackers list and domino trackers get TRACKER show each tracker's collection status (see Collection status), domino trackers records TRACKER pages its records newest first with the same filters as management.trackers.records, domino trackers summary TRACKER counts them, and domino trackers outcomes TRACKER lists its trigger outcomes. Reads need read.
domino trackers ingest TRACKER records.json stores up to 100 records in a custom tracker with ingest permission, and domino trackers retry-outcome TRACKER --quest QUEST --record RECORD --observed-at MS runs admission again for one skipped record. Both are saved before they are sent, so an uncertain answer resumes with the error's operation.resume command. See CLI automation.
Collection status
domino trackers get and management.trackers.get return the published definition, paused, archivedAt for an archived tracker, and these collection fields:
| Field | Meaning |
|---|---|
state | idle between cycles, syncing during one, error after a failed cycle (retried in about a minute), complete once the final cycle after window.end has finished. |
lastStartedAt | When the latest cycle started. |
lastCompletedAt | When a cycle last finished in full. A failed or still-running cycle leaves it unchanged. |
nextSyncAt | When the next cycle is due, or null when nothing more is scheduled: the window has ended, or the source receives records as they happen. |
coverage | complete when the last X cycle exhausted the search and refreshed known posts without a warning, otherwise partial. It is unknown after the first publish, or a publish that changes the definition, until collection reports; and stays unknown for sources that receive records as they happen. |
error | The failure of an error cycle, or a warning from a cycle that finished, such as "X search reached the configured page limit". Read it together with state: a warning with idle or complete means the cycle succeeded with partial coverage. |
records | How many records the tracker holds. |
pauseReason | Why a paused tracker is paused, null otherwise: operator, x-budget-exhausted (the monthly X budget is spent) or test-window-ended (a test X tracker collected for 14 days). See How often Domino reads X. |
resumesAt | When a tracker paused on its X budget resumes on its own: the start of the next UTC month. |
effectiveRefreshSeconds | The interval a scheduled tracker runs at: its refreshSeconds, but no shorter than the project's plan allows, which is six hours on every plan but Enterprise. This holds for X search, YouTube Shorts and TikTok trackers alike; only an X search tracker's deployment warns when its refreshSeconds is shorter. |
Archive a tracker
Archive a tracker with Archive tracker on its page in Trackers, or in Settings → Resources, to stop collecting: scheduled X searches, Discord activity, and records your server sends. Everything already collected stays readable. Choose Unarchive tracker in either place to collect within its window again; a separate pause stays until you resume it. Quest checks that already read the tracker keep what they saw. See resource lifecycle.
Withdraw and restore quest enrollment
Your team can take a member out of a quest that requires enrollment with Withdraw enrollment in Console member details, giving a reason. New activity stops counting for them; their existing attempts, completions and rewards stay. Re-enroll brings them back after confirming consent and starts a new enrollment time. Repeating an active enrollment keeps its current time. This differs from campaign enrollment, which keeps its original time through withdrawal.
Relink retained identities
If a member's account was unlinked, a reviewer can restore it with Relink, under the member's Identities or Wallets in Console. Activity Domino skipped because nobody had linked the account is then looked at again.