Changes are on the way!
Braze Bonfire is read-only from April 6–April 13, 2026. 

Braze Bonfire is getting an upgrade. From April 6 through April 13, 2026, Bonfire will be read-only while we tinker behind the scenes to improve your experience in the community. Read more.

Google Tag Manager

Forum Discussion

Francesca's avatar
Francesca
Collaborator
20 days ago

Build email interaction scoring

Hi there, we send 2 to 3 newsletters per week. Currently, we segment users based on their previous email interaction through segment extensions. For instance, we send one campaign per week to the full database, the second campaign only to users who have opened at least X emails in the last 3 months and the third campaign only to users who have opened at least Y campaigns in the last month or have clicked at least Z campaigns in the past month. Is there a way to build a scoring model based on (real) opens and clicks that also takes into account when the action has occurred? So that the score increases every time a user opens or clicks, but also decreases when a users does not engage for a certain period? Ideally, clicks should have a higher score than opens, and only real opens should be considered.

Every suggestion in much appreciated :)

3 Replies

  • This will need to be tested.

    Based on your request, you would need to create and populate custom user attribute(s) for the scores you want to track by recurring campaigns/canvases to set them via user update or braze to braze webhooks based on your engagement segments.  Use liquid to populate the current value and to add/subtract from it based on what result you are looking for (add logic so you do not create a negative number).

    Opens are not a great engagement measurement at this point even when excluding machine opens. Unique clicks are king (keeping in mind unsub clicks and preference page clicks count in that).

    You might also want to look at bot click filtering filteringhttps://www.braze.com/docs/user_guide/administrative/app_settings/email_settings/bot_filtering

    Set it up and test, test, test

  • One approach you could take could be to compute this score outside of Braze (e.g. in your data warehouse) and then feed it back into Braze as a user attribute or via Segment Extensions.

    As Ted mentioned, unique clicks are typically the strongest engagement signal (excluding things like unsub, app download links, etc). If you have access to data points such as unique_opens_real and/or email_clicks along with their timestamps, you could possibly use those data points to build a more dynamic scoring model.

    For example, you could implement a time-decay model such as:

    Email Decay = User Action × Decay Factor ^ Days Since Action

    Where you might define User Actions as click being worth 5 points, opens worth 2 points and a decay factor of like 0.8 (depending on how aggressive you want engagement to decay)

    Then you could sync the resulting score (or even a tier like High/Medium/Low) back into Braze for segmentation and targeting through a Custom Attribute on whatever cadence you like.

    That's just a thought of mine but definitely keen to hear how others are approaching this. And +1 to Ted’s point - definitely test and validate before rolling out!!

  • Hello Francesca​

    We have not experimented with engagement scoring directly, but we have done something similar around dynamically adjusting email cadence based on user engagement. Instead of a fixed sending frequency for everyone, each user moves up or down in frequency based on their recent activity. This resulted in lower unsubscribes while driving higher revenue for us.

    When measuring activity we considered both clicks and real opens equally, filtering out machine opens (machine_opens = true) to avoid Apple MPP inflating the numbers. On the topic of opens being unreliable, we understand the concern but felt that discarding them entirely means losing all genuine opens in the process. Filtering machine opens and keeping real opens as part of the activity signal felt like the right balance for us.

    All of this is calculated in our data warehouse and the send_cadence attribute is synced to Braze daily via CDI.

    We have tested this extensively and here is what worked for us. Adjust the days based on your own send volumes and engagement benchmarks.

    Reducing for disengaged users:

    • Daily to 3x Weekly if no activity in the last 7 days
    • 3x Weekly to Weekly if the user has been in the 3x Weekly state for 120 days with no activity
    • Weekly to Monthly if the user has been in the Weekly state for 90 days with no activity

    The 120 days in 3x Weekly might seem long but it is intentional. Our data shows that most of our buyers come from the Daily bucket, so the ultimate goal is to move as many users to Daily as possible. Users in 3x Weekly are not disengaged enough to give up on, we keep feeding them content at a reduced frequency hoping they re-engage, and a significant portion of them do come back and jump straight to Daily. The 120 day window gives them enough time and enough touchpoints to find their way back.

    The timer is also based on how long the user has been in that specific cadence state, not just their overall last activity date. So a user does not drop from 3x Weekly to Weekly just because they have not engaged in 120 days overall, they drop only if they have been sitting in 3x Weekly for 120 days without any activity.

    Increasing for re-engaged users:

    • Monthly to Weekly if there was activity yesterday and cadence hasn't changed in the last day
    • Weekly to 3x Weekly if there was activity yesterday and cadence hasn't changed in the last day
    • 3x Weekly to Daily if there was activity yesterday and cadence hasn't changed in the last day

    We move users up quickly and there is a deliberate reason behind this. A user who is engaging every day but not yet converting is telling you they are still looking for inspiration, they just have not found the right thing yet. Increasing their cadence means more chances to show them something that lands. Once a user does make a purchase we apply a cool down period where we pause email communications for a certain number of days, so we are not over-communicating to recent buyers.

    On the flip side, if a user who just moved up to Daily shows no activity for 7 days, they drop back to 3x Weekly quickly. The logic is intentionally asymmetric: slow to reduce for disengaged users, fast to react in both directions around re-engagement.

    How it works in Braze:

    This is all fully automated. All users enter the same daily newsletter Canvas regardless of their cadence. The send_cadence attribute drives everything inside the template itself using Liquid. We define which days of the week each cadence tier receives the newsletter and use Liquid abort logic inside the template to silently skip the send for users who are not scheduled to receive it that day. So a 3x Weekly user enters the Canvas every day but only receives the email on their designated days, same with Weekly and Monthly users. No separate Canvases, no audience splitting, just one Canvas and Liquid handling everything cleanly.

    Happy to go deeper on the implementation if helpful!