@aglyn/plugins-marketing
The Marketing plugin for Aglyn: announcement bars and popups (overlays), A/B experiments, and email campaigns, with the console section that manages them, the runtime that shows them on a published site, and the server routes behind both. Install it if you run the Aglyn console and tenant runtime and want these features; it is a first-party plugin, not a standalone library.
Published to npm from the Aglyn monorepo. Versions follow semantic versioning.
Install
npm install @aglyn/plugins-marketing
Peer dependencies: react, next, @mui/material, @mui/x-data-grid, firebase, and firebase-admin for the server entry.
What's in it
The plugin declares four registrars in plugins.config.json, plus a site module so a published page can load the site half alone.
On a published site (registerMarketingPlugin, the site registrar, exported from @aglyn/plugins-marketing/site). It registers one site runtime, marketing-site-runtime, with registerSiteRuntime. The runtime is not a canvas element: the tenant page renders it generically, and it draws the active announcement bars and popups, applies experiment variants and runs the page's client automations from the data the server enricher wrote. In the editor's Preview, where no enricher runs, it rebuilds that data on the client through a deferred import.
Analytics tags (analyticsProvider, exported from @aglyn/plugins-marketing/analytics-provider). The Google tag adapter behind core's analytics-provider contract: the Google Analytics 4 pair and the Google Tag Manager pair a site configures in its analytics settings (gaMeasurementId, gtmContainerId), with the Consent Mode default in front of each; how a resident Google tag is told a visitor's answer changed (the ga-disable-<id> flag and a consent update); and how an event reaches it. Declared under analyticsProvider in plugins.config.json, so core knows which settings configure a tag without loading it, and loaded only by a published page whose site configures one and by the console, whose own tag the consent controls answer to.
Console (registerMarketingConsole, the console registrar):
- A
Marketingnav item at/marketingwith the sections Overview, Campaigns, Conversions, Overlays and A/B testing. Each section is a route; the page is code-split. - The same page at the organization level,
/[orgSlug]/marketing, declared inorgNavItemswith the site's sections in the site's order. Campaigns and their sends belong to the organization (orgs/{orgId}/emailCampaigns,orgs/{orgId}/campaigns): the org hub lists every one, places a campaign on every site or on chosen sites (visibleTo), and asks which site an email is sent as before writing it; a site's hub lists the campaigns placed on that site. Overlays, A/B tests and conversions are each one site's, so the org hub reads them per site and bounded: Overview sums the org's sends and each site's overlay and test figures as server aggregates, for a capped number of sites; Overlays and A/B testing list every site's, one page of sites at a time, switch an overlay on or off, and send every edit to the site's own hub; Conversions shows the site picked under "Conversions on". Overlays and A/B testing carry their plan flags on the org sections, so an organization without the plan reads nothing per site. Both levels share therelease_marketingflag. The organization's messages are its Emails page's; the old/[orgSlug]/marketing/emails/…addresses redirect there (apps/console/next.config.js). - Campaigns end to end. The plugin owns the campaign composer, test sends, scheduling, reports and recipients. The individual messages are listed on the Emails page, but that page belongs to the email plugin, which hosts an
emailMessageszone; this plugin fills it with the message list, one message's page and its composer. It also fillsemailTemplateReport(what the sends built from a template did) andemailTemplateRecipients(who received them). The campaign's model — its container, a send's report, the message record and a design's report — is this plugin's (src/lib/model/); the rate math every bulk sender divides by is@aglyn/shared-ui-email-campaigns. - Widgets in other hosts' slots: the "Last campaign" card on the site dashboard (
hostDashboard), the campaigns card in the Inbox (inboxCampaigns), campaign attribution on a record's page (crmRecordAttribution,inboxRecordAttribution), and the site's section experiments, reported to the besigner's Interactions section (besignerInteractions), which badges an element with its experiment and starts a draft on a page's element. - Zones this plugin hosts for other plugins to fill, registered with
registerPluginZone: two on the A/B testing card (beside the variants, and below a test's results), and five bare zones in the campaign composer and on a message's page for whichever plugin keeps the mail itself: the topic picker, the topic options, the add-a-sender editor, the design creator and the sent-design preview. Two more bare zones sit on the Overlays section:hostOverlays, beside New bar and New popup, whose widget hands proposed copy to the list, which writes the overlay switched off; andoverlayEditor, among the overlay editor's fields, whose widget fills the fields unsaved. A barehostCampaignszone sits beside Create campaign on the Campaigns section, a site's or the organization's; its widget is handed the site (or, on the organization's hub, the sites a campaign could be placed on) and writes nothing through the list. A baremarketingInsightszone sits in the header of the Conversions section and of a campaign's report; its widget is handed the site the figures are one site's and reads them only through the figure readers this plugin registers (marketing.campaigns,marketing.experiments,marketing.conversions,marketing.revenue). - A record route for
campaign, at both the site and the organization level, so another plugin can link to a campaign without knowing this plugin's URLs. - A record list source for
overlay(plugin-record-lists): a site's announcement bars and popups, named, for another plugin's picker — the automation editor's "Show overlay" step — to list without reading this plugin's collection.
Server, exported from @aglyn/plugins-marketing/server:
registerMarketingApi(thetenantApiregistrar): theexperiments/trackbeacon, which counts exposures and conversions for a running experiment and can finish a test whose auto-winner rule is met, and a site page enricher (registerSitePageEnricher) that adds overlays, automations and experiments to a page's data.- From its server declarations, the site collector's
overlaybeacons (registerPluginSiteBeacon): each bar and popup event the site runtime reports is counted into the site's day document and the overlay's own counters, after the collector's host and lockdown gates. - From its server declarations, the platform's conversion creditor (
registerPluginConversionCreditor,plugin-conversion-credit): every door that produces an outcome — a form submission, a booking, a member sign-up, a newsletter opt-in, the contact and the lead the record system files for them, an order and its refund, and what a sequence's mail led to — asks it where the visitor arrived from and which campaign to credit. It answers with the last-touch join over the visitor's UTM labels and the campaign mail they clicked (server/campaign-conversion-attribution.ts), the order revenue join (server/email-revenue-attribution.ts), the per-site click touch kept on the person's delivery document (server/email-campaign-touch.ts), the sequence outcomes counted under a campaign, and the person's erasure of all of it. - From its server declarations, the send tally the site's unsubscribe page tells when a recipient leaves from a campaign send's mail (
registerPluginSendTally,plugin-send-tallies), which counts it on the send. - From its server declarations, the
emailSendrecord index (plugin-record-index): the organization's sends, named, which the CRM names the campaign mail on a person's timeline by. registerMarketingConsoleApi(theconsoleApiregistrar):campaigns/send,campaigns/manage,campaigns/recipients,campaigns/process-scheduled,lists/materialize, and the delivery events webhook atemail/events. It also registers draft writers on the core's resource-drafts seam —campaign,overlay(written switched off) andexperiment(written stopped, its variants as drafts) — the AI build capabilitiesoverlayandexperimentthat name the last two (server/marketing-ai-capabilities.ts), and figure readers for campaign, experiment, conversion and revenue results.
Exports from .
registerMarketingConsole,registerMarketingPlugin,BUNDLE_ID.- Overlays:
HostOverlay,resolveActiveOverlays,overlayMatchesPath,overlayActiveAt,overlayStatus,compareOverlayPrecedence,popupSuppressed. - Experiments:
HostExperiment,ExperimentVariant,assignExperimentVariant,validateExperiment,compareVariants,evaluateAutoWinner,experimentResultRows,describeVariantComparison. - The site contract types (
AnnouncementBarData,PopupData,ScreenExperiment,ClientAutomation),compileClientAutomations, and the campaign figures helpers (campaignFormsRollup,campaignFormTotals).
Usage
The plugin is loaded through Aglyn's plugin manager: the generated loader manifests import the package and call the registrars named in plugins.config.json, and a published page loads the site half only where the site runs the feature. An app that wires plugins by hand calls them once at startup:
// published site, client side: the site half alone
import { registerMarketingPlugin } from '@aglyn/plugins-marketing/site'
registerMarketingPlugin()
// console, client side
import { registerMarketingConsole } from '@aglyn/plugins-marketing'
registerMarketingConsole()
// server side: tenant runtime and console
import {
registerMarketingApi,
registerMarketingConsoleApi,
} from '@aglyn/plugins-marketing/server'
Import the site half from ./site, not from the root: the root entry also carries the console registrar and its pages.
How it fits
A plugin package (scope:plugin). It depends on the core (@aglyn/aglyn), the tenant packages (@aglyn/tenant-runtime, @aglyn/tenant-data-admin, @aglyn/tenant-feature-instance) and generic @aglyn/shared-* packages. It imports no other plugin. Everything it shares with the email, CRM, Inbox, commerce and AI plugins crosses through core seams: console zones and slots, record routes, resource drafts and figure readers. The core never imports this package.
License
Apache-2.0. Source: https://github.com/aglyn/aglyn/tree/main/libs/plugins/marketing