Settings reference
Every key the newsletter reads lives in user/config/plugins/kahunacart-newsletters.yaml. Every key on this page except the provider block has a field on the settings screen. The defaults are the ones the plugin ships.
Where these are edited
KahunaCart → Newsletters → Settings. This is Grav's own configuration form, built from this plugin's blueprint, the same form the Grav admin's Plugins → KahunaCart Newsletters page draws. The Save button in the admin's header saves it.
The form needs KahunaCart 1.2.0 or newer. On an older one the Settings screen says so and links to the Grav admin's page for this plugin.
Important
Settings save where the admin's environment picker says. With the picker on Default that is the base config; with a named environment chosen it is that environment's copy. The Providers tab writes its secrets into the same file.
Three fields on the form are checks rather than settings.
| Field | What it draws |
|---|---|
transport_status |
Can this store send mail?, at the top of the Sending tab: who campaigns go out as, whether the Grav Email plugin is installed and enabled, which engine it uses, and whether the one-click unsubscribe headers survive that engine. |
worker_status |
One line about the queue worker, under the three sending numbers. |
providers_cards |
The whole Providers tab: one card per transport plugin that can report deliveries, with the webhook URL, Generate a secret and Set up in \<provider>. See Delivery reports and providers. |
The master switch
| Key | Default | What it does |
|---|---|---|
enabled |
true |
Off, the plugin registers its permissions and declares its tables to bin/plugin kahunacart reset, and does nothing else: no routes, no jobs, no admin section. The rows stay in the database. |
Sending
| Key | Default | What it does |
|---|---|---|
sending.per_minute |
60 |
How many messages the store sends per minute, across every campaign. Set it to what your mail transport allows. |
sending.batch |
50 |
How many recipients one run of the send job takes on before it hands the worker back. Smaller means a busier queue and more responsive pausing; larger means fewer job rows. |
sending.abort_after_failures |
25 |
Consecutive send failures that pause a campaign and raise an alert. A single success resets the count. |
from_name |
empty | The name campaigns are sent as. Empty falls back to the Grav Email plugin's setting. A list can override it. |
from_email |
empty | The address campaigns are sent from. Same fallback and the same per-list override. It has to be an address your transport is allowed to send as. |
Tracking
| Key | Default | What it does |
|---|---|---|
tracking.opens |
true |
Whether campaigns get an open pixel by default. A campaign can override it. Only a timestamp on the send row is stored. |
tracking.clicks |
true |
Whether links in a campaign are rewritten through the store's own click redirect by default. Stores a timestamp and a per-link count. |
tracking.retain_days |
365 |
How long individual click and provider-event rows are kept before the retention sweep removes them. The campaign's own counters survive the sweep. |
utm.enabled |
true |
Whether campaign links that point back at this store carry UTM parameters. Links to anywhere else are never tagged. |
utm.source |
newsletter |
What utm_source says on every campaign that does not override it. |
utm.medium |
email |
What utm_medium says. email is what makes a report's Email channel include your campaigns. |
utm.campaign |
empty | What utm_campaign says. Empty means each campaign uses a slug of its own name. |
utm.content |
empty | What utm_content says. Leave it empty: it tells two versions of one campaign apart, so it belongs on the campaign. |
Signup
| Key | Default | What it does |
|---|---|---|
double_opt_in |
true |
The default for a new list. A list with it on sends a confirmation email and does not mail anybody who has not clicked it. |
consent_text |
I agree to receive email from this store. I can leave with one click at any time. |
The sentence the signup partial shows beside the opt-in box. A hash of it is stored against each subscriber when they agree. Changing it affects new subscribers only. |
unsubscribe.confirm_on_get |
false |
Whether the unsubscribe link acts on being opened rather than on a button press. Leave it off: mail scanners follow every link in an inbox before the person does. |
import.keep_days |
30 |
How long an uploaded contact list is kept on disk, counted from the upload. The file is removed as soon as its import finishes; this is the safety net for an upload whose job never ran. 0 keeps them forever. |
Public links
| Key | Default | What it does |
|---|---|---|
confirm.on_get |
false |
Whether the double opt-in link confirms the moment it is opened, rather than drawing a page with one button. Leave it off. Separate from unsubscribe.confirm_on_get, so a store can set one without the other. |
confirm.auto_submit |
true |
Whether the confirmation page presses its own button the moment it loads, so a person who clicked the email lands on "you are on the list" without a second click. A spam filter that does not run scripts still only sees the button. Turn it off to require the click. |
rate_limits.subscribe |
10 |
How many times one visitor address may post the signup form in an hour. Zero turns the limit off. |
rate_limits.token |
60 |
Requests an hour, per address, across the confirm, unsubscribe, preference-centre and view-in-browser pages. |
rate_limits.tracking |
600 |
Requests an hour, per address, for the open pixel and the click redirect. Keep it high: a company reading its mail through one gateway is a single address. |
rate_limits.webhook |
6000 |
Requests an hour, per address, at the provider webhook. Keep it high: a campaign to forty thousand people produces forty thousand delivery reports from a handful of the provider's addresses. Zero turns it off. |
To keep every limit in one file, write security.rate_limits.newsletter_subscribe: {limit: 20, window: 3600} in KahunaCart's own config. The plugin's own key wins when both are set.
Segments
| Key | Default | What it does |
|---|---|---|
segments.count_every_minutes |
15 |
How often the worker recounts the segments whose numbers have gone stale, twenty-five at a time. Every screen prints how old its number is. Zero recounts on every worker run, which is useful while building a segment and not something to leave on. |
Automations
| Key | Default | What it does |
|---|---|---|
automations.enabled |
true |
Whether the automations run at all. Disabling it pauses every flow, preserves enrolments and lets subscribers resume from their current step when you enable it again. Use it while moving a store or changing a transport. |
automations.per_tick |
200 |
How many people one run of the automation tick moves on by a step. A run that hits the number queues itself again straight away, so this caps one run, not how fast a backlog drains. |
Audience
| Key | Default | What it does |
|---|---|---|
checkout.list |
empty | Which list somebody joins when they tick the opt-in box at checkout, named by its code. Empty falls back to the store's first list in the order on the Audience screen, not the one flagged as the default. |
Health
| Key | Default | What it does |
|---|---|---|
deliverability.sending_domain |
empty | The domain the Health tab checks SPF, DKIM and DMARC on. Leave it empty on almost every store: the tab works the domain out from the from address. Set it only when the two differ. |
deliverability.dkim_selector |
empty | The DKIM selector to look for, when the transport cannot be asked for it. Put the part before ._domainkey here. Two selectors during a rotation is fine: separate them with a comma. |
deliverability.return_path |
empty | The host your provider had you CNAME into their return-path zone. Normally the provider is asked for it; set it when that is not possible. |
alerts.bounce_rate_percent |
5 |
The bounce rate, as a percentage of what this store sent in the last thirty days, above which the admin strip warns you. |
The provider block
These are config-only: they have no field on the settings form. Generate a secret on each provider's card mints the secret and shows it in the webhook URL beside it. You can still set any of them by hand in user/config/plugins/kahunacart-newsletters.yaml.
| Key | Default | What it does |
|---|---|---|
providers.smtp2go.secret |
empty | The random string in the path of SMTP2GO's webhook URL. SMTP2GO does not sign its webhooks, so this secret is the whole of the authentication. |
providers.smtp2go.auth_header |
empty | Optional. If you set an Authorization header on the SMTP2GO webhook by hand, put the whole value here, including the word Bearer or Basic. It is checked in constant time alongside the path secret. |
providers.ses.secret |
empty | The path secret in the URL you point an SNS topic at. There is no key beside it: Amazon signs every message with a certificate. |
providers.postmark.secret |
empty | The path secret in Postmark's webhook URL. Postmark does not sign its webhooks; the basic auth pair it offers instead lives in the email-postmark plugin's settings. |
providers.mailgun.secret |
empty | The path secret in Mailgun's webhook URL. Mailgun signs as well, with the HTTP webhook signing key in the email-mailgun plugin's settings. |
providers.sendgrid.secret |
empty | The path secret in SendGrid's webhook URL. SendGrid signs as well, with the verification key in the email-sendgrid plugin's settings. |
providers.resend.secret |
empty | The path secret in Resend's webhook URL. Resend signs with Svix as well, with the signing secret in the email-resend plugin's settings. |
Five more keys per provider are written under providers.<name> by those buttons. They are records rather than settings, so they have no default.
| Key | Written when |
|---|---|
secret_at |
Generate a secret minted the current address. |
webhook_id |
Set up in \<provider> created a webhook, where the provider gives one an id. |
webhook_events |
The same, naming what it registered. |
set_up_at |
The same, saying when. |
webhook_dead_at |
A new secret was minted over a live registration, so the webhook in the provider is now posting at an address that answers 404. |
The card reads them, and the "has said nothing" alert counts only mail sent after secret_at or set_up_at, whichever is later. Deleting them costs you the sentence on the card and nothing else.
Permissions are not configuration
kahunacart.newsletters.view, .manage and .send are Grav account permissions, set per user or per group in Accounts, not keys in this file. See Newsletters.