Skip to content

Releases: goldnead/statamic-marketing

2.41.0

Choose a tag to compare

@goldnead goldnead released this 28 Oct 09:35

Added

  • [new] The subscriber table of a list links each address to its LeadHub contact, resolved like the
    campaign report does (normalised address, one lookup per page, no link for readers without
    the contact permission, plain text when there is no contact).

Fixed

  • [fix] The campaign "send at" field is read in marketing.display_timezone (default Europe/Berlin,
    env MARKETING_DISPLAY_TIMEZONE, falls back to app.timezone) instead of app.timezone. Typing
    07:00 no longer sends at 08:00 or 09:00 on a UTC application. Stored times stay UTC and
    app.timezone is untouched; already scheduled campaigns do not move. The editor, the campaign
    listing and the report show scheduled and sent times in the same zone, with its abbreviation.

2.40.0

Choose a tag to compare

@goldnead goldnead released this 28 Oct 08:50

Changed (behaviour change, read before updating)

  • A campaign that already has a variant subject and an ab_share of 10 to 50 now sends as an A/B test with a winner pass instead of going to the whole audience. Before this release the value was stored and ignored, so such a campaign (draft or scheduled) sent to everybody, half and half. There is no opt-in: after the update it is mailed to the test share first and the rest follows after the wait. To see which campaigns this affects, run php artisan marketing:ab-campaigns (read only) before updating; to keep the old behaviour for one of them, set its test share to 0.
  • One migration runs with the update: the table marketing_ab_decisions, the claim on the winner decision.

Added

  • A/B winner send. marketing:send-ab-winners, scheduled every minute, sends the subject with the higher open rate to the rest once marketing.ab.wait_minutes (default 240) have passed. A tie, or fewer than marketing.ab.min_per_variant (default 10) delivered mails in either variant, sends variant A; the reason is stored in meta.ab. Campaigns with ab_share 0 send as before.

2.39.2

Choose a tag to compare

@goldnead goldnead released this 23 Oct 01:27
8efdb21

Percent-encoded login link paths are recognised in click tracking. See CHANGELOG.md.

2.39.1

Choose a tag to compare

@goldnead goldnead released this 23 Oct 00:29
7d2562a

Click tracking keeps only the target path of a signed login link, never its signature (event row, MessageClicked payload, campaign report, message_clicked node). See CHANGELOG.md.

2.39.0

Choose a tag to compare

@goldnead goldnead released this 22 Oct 23:07
bd488d4

Links in a sent mail to a page behind the login log the recipient in (optional, needs statamic-identity-contracts 1.3). See CHANGELOG.md.

v2.38.0

Choose a tag to compare

@goldnead goldnead released this 22 Oct 16:01
283cd58

MessageEngagement::forMessages(): what became of a set of mails, counted in people (proxy opens apart). See CHANGELOG.

v2.37.0

Choose a tag to compare

@goldnead goldnead released this 21 Oct 19:02

Probelauf: marketing.send_email rendert seine Mail für die Landkarte (mailPreview), ohne zu senden, zu schreiben oder zu zählen. Siehe CHANGELOG.

v2.36.0

Choose a tag to compare

@goldnead goldnead released this 20 Oct 16:31

Added: the newsletter as a card on the funnels map

brand-context's funnels map can now point at the newsletter. It is one fixed object (type newsletter, id newsletter) linking to the campaigns list, with a note that people inside a running sequence that pauses the newsletter are left out. No on/off switch and no weekday are shown, because this addon stores neither. The card's number is newsletter-class mails sent in the period, and it is absent (not zero) when there is no newsletter campaign. No migration, no config.

2.35.0

Choose a tag to compare

@goldnead goldnead released this 20 Oct 11:18
5fdc052

2.35.0 - 2026-10-20

Added: SubscriptionService::subscribeWithConsent(), a sign-up that records how consent was given

A subscription can now carry the consent it rests on, in meta.consent: the method (for example booking_checkbox), the list, the exact wording the person was shown (text, with its SHA-256 as text_sha256), the source, when it was given (requested_at) and when it was confirmed (confirmed_at).

  • Without double opt-in the address is subscribed at once and confirmed_at is the time of the consent.
  • With double opt-in the normal confirmation runs. confirmed_at stays empty until the confirmation link is used, and is written then.
  • An address already subscribed is left exactly as it was, with the consent it already has.
  • An empty method, text or source, or a given_at that is not a date, throws InvalidArgumentException.

Added: the automation node marketing.check_received ("Check Mail Received")

Asks whether an address has already been sent a marketing mail, and can end the run on the answer. Modes report (default), require and forbid, as the check node for access does. Optional filters: template and campaign (comma-separated handles; a mail matching either counts), within_days, and today (since the start of the current day in marketing.day_gate.timezone). Outputs received, count and last_at. Counts mails with status sent, bounced or sending (stamped), so two parallel runs cannot both send; pending, failed, skipped and capped rows do not count. An unreadable address or a failed lookup is a failure, not a "no". within_days takes whole days only; 1.5 is refused, not cut to 1.

Added: the automation node marketing.check_tag ("Check Subscriber Tag")

Asks whether the subscription of an address on one list carries a tag, the one a tag link put there, and can end the run on the answer. Same modes as above. With LeadHub installed the tags are read from the person's contact, where the tag link writes them; and meta.tags on the subscription is read in both cases. Tags are compared by slug on both sides, so "Wants Freebie" on the contact and wants-freebie in the node are the same tag. No subscription on the list is an answer (has_tag and subscribed both false), not a failure. Outputs has_tag, subscribed and tags.

Added: newsletter_day_gate can also hold back "one marketing mail per day"

Two new optional fields: one_per_day (default off) and email (tokenable; empty uses the address the run is about). With one_per_day on, a run that has already sent this address a marketing mail today waits until tomorrow at the same time, as it does for a campaign. The node's output now carries reason: campaign or mailed_today.

Upgrading

  • No migration, no config.
  • The two new newsletter_day_gate fields are optional and off by default. Graphs saved before keep their behavior; the node's output gains reason when it blocks.

v2.34.0

Choose a tag to compare

@goldnead goldnead released this 19 Oct 08:25
381c70f

The newsletter leaves out people inside a running sequence that pauses it (automations >= 2.31), per-campaign 'Send anyway', count in report. See CHANGELOG 2.34.0.