Skip to main content

TL;DR

An objective is the event Notifizz watches to decide a campaign “worked”. You set it on the campaign (a click, a read, a custom event like purchase.completed). Notifizz then credits one conversion per unique recipient who received the campaign and triggered the objective afterwards.
  • Pick from Click, Read or any of your custom events.
  • Conversions are deduped per recipient — the same user doesn’t count twice.
  • The dashboard shows who converted (last 50) and every objective evaluation in the Outbox tab for debugging.

Setting an objective

In the campaign editor, the recipients box has an objective row at the bottom. Click it to choose:
  • Click — fires when a recipient clicks any button you placed in the notification. No identity work needed: Notifizz wires the click through a redirect URL it generates per message.
  • Read — fires when the notification is marked read in the inbox widget.
  • A custom event — any event in your catalog. Notifizz credits the conversion when the event payload carries a canonical identity (id, email, pushId, or phone) that matches a recipient who got this campaign.
The objective is per campaign: two campaigns targeting the same event each get their own credit count.

How conversions are credited

Two paths exist, both honour the same dedup rule (one credit per recipient per campaign).

Fast path — receipt-based

The default for Click, Read, and custom events whose payload already carries identity. Notifizz looks up “did this recipient receive a message from this campaign?” — if yes, credits a conversion. One Firestore lookup, no custom code.
// Your SDK call — identity flows through `properties`
client.track('purchase.completed', {
    properties: {
        email: 'alice@example.com',  // canonical identity
        amount: 4990,
    },
});

Custom resolution — onObjective

When the event doesn’t carry canonical identity directly (only an internal ref, a Stripe customer id, etc.), your orchestrator can export a second hook that resolves it server-side:
export const onObjective = async (event: Event, sdk: Sdk): Promise<Identity | null> => {
    const { user } = await sdk.enrichWith('UserByStripeCustomer', {
        stripeCustomerId: event.properties.stripeCustomerId,
    });
    if (!user) return null;
    return { id: user.id, email: user.email };
};
The hook returns { id?, email?, pushId?, phone? } | null. null means “this event does not qualify” — fine, the conversion is simply not credited. Notifizz routes the event through a cloud function only when this hook is exported. Without it, the fast path runs.

Who converted

The campaign performance panel surfaces the latest 50 converted recipients — first identity, relative time, source event. Click the row to drill into the message that ultimately produced the conversion.

Debugging in the Outbox

The Outbox has two tabs:
  • Notifications — every workflow run (delivered, no-recipient, failed, in-progress).
  • Objectives — every objective evaluation, regardless of outcome.
Objective outcomes you’ll see:
OutcomeWhat it means
ReachedFirst time this recipient triggered the objective on this campaign — counted.
Already countedSame recipient triggered it again — deduped, no double credit.
No messageThe event matched the objective but the recipient never received the campaign.
No identityNo canonical field on the event (or onObjective returned null).
FailedonObjective threw or timed out — fix the code, the next event runs fresh.
Click any row to see the inflated event payload, the resolved identity, condition traces, and any error.

Privacy

Notifizz holds no customer data — only the canonical identity fields needed to dedup conversions (id, email, pushId, phone), stored on the dedup index. Conversion rows for the “Who converted” widget are pruned on the same retention schedule as workflow runs.