Compose & send a push
The TwistCue push composer respects the 3/day cap hardcoded on the backend and shows you the number of users who will be dropped before you send. This is the single most important safety net in engagement: respect it.
Engagement → Push (/engagement/push or /push) is the composer + campaign list.
Compose
Section titled “Compose”- Name: internal-only, for the history log.
- Audience: pick a saved segment (Create a segment).
- Content:
- Title (localized EN/AR/ID)
- Body (localized EN/AR/ID)
- Deep link: where tapping opens the app (e.g.
twistcue://series/{seriesId}) - Category:
drops,marketing,moderation,product(users can opt out per category)
- Schedule: Send now, or pick a datetime (UTC).
Estimate & cap preview
Section titled “Estimate & cap preview”Click Estimate before sending. The composer runs the segment query and reports:
Targeted: 21,340 users - Capped: 1,213 users (would exceed 3/day) - Category opted-out: 2,041 usersDeliverable: 18,086 usersThe 3/day cap is enforced server-side in push-scheduler.cron.ts. It counts pushes in the past 24 hours per user, per category-hierarchy. If a push would be the user’s 4th, it’s silently dropped from the send list and logged.
Send now vs schedule
Section titled “Send now vs schedule”- Send now: flushes to the delivery queue immediately. Cron picks it up on the next minute.
- Schedule:
PushCampaign.status='scheduled'withscheduled_at. Thepush-schedulercron (every minute) picks up scheduled campaigns whose time has passed.
Delivery pipeline
Section titled “Delivery pipeline”sequenceDiagram autonumber participant Cron as push-scheduler cron participant DB as Postgres participant Filter as cap filter participant APNs as APNs (iOS) participant FCM as FCM (Android)
Cron->>DB: fetch scheduled campaigns due DB-->>Cron: [campaign_a, ...] Cron->>DB: resolve segment → user_ids Cron->>Filter: apply 3/day cap + opt-outs Filter-->>Cron: deliverable_user_ids Cron->>DB: fetch device tokens for user_ids Cron->>APNs: batch push (iOS tokens) Cron->>FCM: batch push (Android tokens) APNs-->>Cron: delivery receipts FCM-->>Cron: delivery receipts Cron->>DB: update campaign metrics (sent, delivered, opened)History & metrics
Section titled “History & metrics”Every campaign shows in the list with:
- Sent: users the platform accepted the push for.
- Delivered: carrier ack received.
- Opened: users who tapped through (attribution window: 4 hours).
- Open rate: opened / delivered.
Healthy open rates on TwistCue: 8–15% for drops category, 3–8% for marketing.
Gotchas
Section titled “Gotchas”- The 3/day cap is per user, not per campaign. A user targeted by three campaigns in the same day will get one push and be silently dropped from the other two.
- APNs and FCM are stubbed in v2. See Integrations status: the delivery pipeline builds and logs but doesn’t hit real providers until you configure APNs P8 + FCM service account keys.
- Deep links: must match a mobile-registered scheme (
twistcue://…). Bad deep links open the app to the home screen (fallback). - Localized content: the delivery layer picks the language matching the user’s device locale. Missing translation falls back to EN.
- Category opt-outs: users can turn off any category from mobile Settings. Opted-out users are counted as “not deliverable” and don’t consume from their 3/day.
API calls
Section titled “API calls”| Action | Endpoint |
|---|---|
| List campaigns | GET /v1/admin/push/campaigns |
| Detail | GET /v1/admin/push/campaigns/:id |
| Create | POST /v1/admin/push/campaigns |
| Update | PUT /v1/admin/push/campaigns/:id |
| Delete | DELETE /v1/admin/push/campaigns/:id |
| Estimate | POST /v1/admin/push/campaigns/:id/estimate |
| Send now | POST /v1/admin/push/campaigns/:id/send |
| Schedule | POST /v1/admin/push/campaigns/:id/schedule |
| Unschedule | POST /v1/admin/push/campaigns/:id/unschedule |
Full details in API: Engagement.