Latest donator from any source
You have Ko-fi and Streamlabs connected. Both track a latest donor. Which one is actually the most recent? This is what latest() is for, and it is the piece of Overlabels nobody finds on their own.
The problem
Connect Ko-fi and you get [[[c:kofi:latest_donor_name]]]. Connect Streamlabs and you get
[[[c:streamlabs:latest_donor_name]]]. Connect all five donation services and you have five separate
"latest donor" values, each true about its own service and none of them true about your stream.
Put both on screen and your overlay shows two names, one of which is hours stale. Pick one and you are ignoring the other service entirely.
You want one name: whoever donated most recently, wherever it came from.
Every control knows when it changed
This is the part that makes it work, and it is easy to miss.
Every control has an automatic _at companion holding the Unix timestamp of when it last changed.
You never create it and you cannot forget to update it - it exists for every control, always:
c:kofi:latest_donor_name -> "Marijke"
c:kofi:latest_donor_name_at -> 1755381240
So "which service donated most recently" is just "which _at is the biggest number".
latest() picks the winner
latest() takes pairs of value, label and returns the label that came with the highest value. Feed
it timestamps as the values and names as the labels, and it hands back the name attached to the most
recent timestamp.
Create an Expression Control with the key newest_donor:
latest(
c.kofi.latest_donor_name_at, c.kofi.latest_donor_name,
c.streamlabs.latest_donor_name_at, c.streamlabs.latest_donor_name
)
Then use it like any other control:
Latest tip: [[[c:newest_donor]]]
One name. Always the right one.
Expressions use dots where tags use colons. [[[c:kofi:latest_donor_name]]] in a template is
c.kofi.latest_donor_name in an expression. Same value, different place.
All five services
The keys are identical across Ko-fi, Streamlabs, Fourthwall, Buy Me a Coffee and Throne, so extending this is copy and paste:
latest(
c.kofi.latest_donor_name_at, c.kofi.latest_donor_name,
c.streamlabs.latest_donor_name_at, c.streamlabs.latest_donor_name,
c.fourthwall.latest_donor_name_at, c.fourthwall.latest_donor_name,
c.bmac.latest_donor_name_at, c.bmac.latest_donor_name,
c.throne.latest_donor_name_at, c.throne.latest_donor_name
)
Only list the services you have actually connected. A service you have not connected has no controls, so its terms resolve to nothing and it never wins - but leaving them out keeps the expression readable.
The amount, and which service it was
latest() returns whichever label you paired with the winning timestamp, so the same trick gives you
anything about that donation. Three more expression controls:
newest_donor_amount:
latest(
c.kofi.latest_donor_name_at, c.kofi.latest_donation_amount,
c.streamlabs.latest_donor_name_at, c.streamlabs.latest_donation_amount
)
newest_donor_currency:
latest(
c.kofi.latest_donor_name_at, c.kofi.latest_donation_currency,
c.streamlabs.latest_donor_name_at, c.streamlabs.latest_donation_currency
)
newest_donor_service:
latest(
c.kofi.latest_donor_name_at, "Ko-fi",
c.streamlabs.latest_donor_name_at, "Streamlabs"
)
Note that all of them compare the same timestamps - latest_donor_name_at in every case. That is
deliberate. You are answering one question ("which service went last?") and then reading several
different facts off the winner. Comparing latest_donation_amount_at in one and
latest_donor_name_at in another could pick two different services and pair a name with someone else's
number.
Then:
[[[c:newest_donor]]] tipped [[[c:newest_donor_amount|currency:EUR]]] via [[[c:newest_donor_service]]]
Hiding it before the first donation
With nothing donated yet, every timestamp is the moment the control was created and the name is empty, so you get a card with a blank in it. Wrap it:
[[[if:c:newest_donor]]]
<div class="tip-card">
<span class="tip-label">Latest tip</span>
<span class="tip-name">[[[c:newest_donor]]]</span>
<span class="tip-amount">[[[c:newest_donor_amount|currency:EUR]]]</span>
</div>
[[[endif]]]
Biggest instead of most recent
Same shape, different question. argmax() compares numbers rather than timestamps, so pairing amounts
with names gives you the largest single tip instead of the newest:
argmax(
c.kofi.latest_donation_amount, c.kofi.latest_donor_name,
c.streamlabs.latest_donation_amount, c.streamlabs.latest_donor_name
)
That comparison is currency-naive. It compares 50 against 40 without caring that one is JPY and the
other EUR. If your donations arrive in mixed currencies, argmax() will confidently pick the wrong
one. latest() has no such problem, because a timestamp is a timestamp.
Where next
- Expression Controls - the whole math layer, including
oldest(),argmin(),clamp()and the worked GPS distance example - Controls - what controls are and how the service-managed ones work
- Integration Presets - every auto-managed control across every service, searchable