ConvertKit - v1.0.0
Feeds
A feed is the join between an artisanpack-ui/forms form and a Kit destination. One form can have many feeds — for example, one feed that sends every submission to a general newsletter, plus a second feed that only fires for enterprise plans and adds an Enterprise Lead tag.
Schema
The convertkit_feeds table:
| Column | Type | Notes |
|---|---|---|
id |
bigint | Primary key. |
form_id |
bigint | FK to the forms package's forms table. Resolved lazily via the KitFeed::form() relationship. |
name |
string | Human-readable label. Shown in admin UIs, logs, and CLI output. |
kit_form_id |
bigint, nullable | Kit form to subscribe to. null means the job falls back to subscribers()->create() + per-tag applies. |
kit_tag_ids |
json | Array of Kit tag ids to apply. Default []. |
field_map |
json | Kit destination → submission slug map. See Field Mapping. |
conditional_logic |
json, nullable | Rules that must pass for the feed to fire. See Conditional Logic. |
is_active |
boolean | Master toggle. Inactive feeds are ignored by the listener and by the public subscribe endpoint. |
created_at / updated_at |
timestamps |
The form() relationship
The related model class is resolved from config at call time — convertkit.forms_integration.form_model — so the forms package remains an optional peer.
$feed = KitFeed::find( 1 );
$form = $feed->form; // ArtisanPackUI\Forms\Models\Form (or your custom model)
If the configured class doesn't exist, KitFeed::form() throws a descriptive RuntimeException at access time — never an opaque Class "" not found fatal.
Creating a feed
Four options, from lowest to highest ceremony:
CLI wizard
php artisan convertkit:feeds create
Walks you through form id, name, kit form id, email slug, and tags. Full docs: Artisan Commands.
REST API
POST /admin/convertkit/feeds
Full spec: Feed Admin.
Directly via Eloquent
use ArtisanPackUI\ConvertKit\Models\KitFeed;
$feed = KitFeed::create( [
'form_id' => 5,
'name' => 'Newsletter',
'kit_form_id' => 12345,
'kit_tag_ids' => [ 100 ],
'field_map' => [
'email_address' => 'email',
'first_name' => 'name',
],
'is_active' => true,
] );
Via the factory (tests)
KitFeed::factory()->create();
KitFeed::factory()->inactive()->create();
Dry-running a feed
Before you flip a feed to is_active = true, dry-run it against a representative submission payload:
POST /admin/convertkit/feeds/{id}/test
{
"values": { "email": "jane@example.com", "plan": "pro" }
}
Returns { would_send, reason, payload } without touching Kit. Full spec: Feed Dry-Run.
Feed evaluation order
The listener loads feeds ordered by id ASC and evaluates them independently. There is no cross-feed short-circuit — a "wins" or "loses" feed does not affect the next one. If two feeds both match, they both fire.
Inactive feeds
is_active = false is a hard stop:
- The listener skips inactive feeds entirely (no
KitFeedSkippedevent fires). - The public subscribe endpoint returns a generic 422 for an inactive
feed_id— see Public Subscribe.
Use this to pause a feed without deleting it. Feed history (dispatched jobs, KitSubscribed events) stays intact.
Deleting a feed
Deletion removes the row but does not touch any subscribers already at Kit. If you need to also strip a tag from previously-subscribed users, you'll need a separate one-shot script that iterates and calls subscribers()->untag().
php artisan convertkit:feeds delete {id}
Asks for confirmation before deleting.