Actions and results
What each Marketing button and automatic behaviour does, with worked numbers and what the system refuses.
On this page (25)
Marketing Dashboard
| Action | When | What you do | What happens |
|---|---|---|---|
| Tiles follow the period | Two campaigns with delivery and attributed leads in the last 90 days | Open Dashboard; switch Last 30 -> Last 90 days | Spend, Leads, Orders, Revenue, Gross Profit change to the new period; CPL = Spend / Leads; ROAS = Revenue / Spend (2 decimals) |
| Counts tiles | 1 active campaign, 1 active journey, 2 active rules, 3 audiences | Open Dashboard | Active campaigns 1 (3 audiences); Active journeys 1 (2 rules); Opted in / opted out match Consent tabs |
| Funnel and sources | Leads from 2 sources (e.g. Instagram Lead Ads, Website Form) | Look at the 'Social-to-cash funnel' and 'Leads by source' cards | Funnel steps Impressions > Clicks > Leads > Qualified > Opportunities > Quotations > Orders > Invoices; sources sorted by leads |
| Top campaigns open the record | Campaigns with revenue | Click the first row of 'Top campaigns by revenue' | Campaign record opens (/marketing/campaigns/<id>); at most 5 rows, highest revenue first |
Campaigns
| Action | When | What you do | What happens |
|---|---|---|---|
| Create a campaign | marketing.campaign.edit | Campaigns > New; Name 'Ramadan Offers 2026', Objective Lead generation, Channels Instagram+WhatsApp, Start/End, Budget 15000, Status Draft; Save | Saved; Code CMP-000n; currency AED; utm_campaign 'ramadan_offers_2026'; Audit log 'marketing.campaigns.saved' |
| End before start refused | New campaign; Start 2026-10-10, End 2026-10-01; Save | Refused: 'The end cannot be before the start.' on End | |
| Required fields | New campaign; leave Name and Status empty; Save | 'Campaign is required.' / 'Status is required.'; nothing saved | |
| Search and export | 5 campaigns | Type part of a name in Search; Export | Rows filter as you type (all listed columns searched); CSV has the listed columns with the shown text |
| Codes do not repeat | Campaigns CMP-0001..CMP-0003 | Create another campaign | Gets CMP-0004 (never an existing code) |
| Delete a campaign that has leads (API) | Campaign with an attributed lead | DELETE .../marketing/registers/campaigns/<id> | Refused: 'A campaign that has run or has leads is cancelled or completed, not deleted.'; also refused for status Active/Paused/Completed |
Campaign record
| Action | When | What you do | What happens |
|---|---|---|---|
| Header and tiles | Campaign with delivery and attributed leads | Open the campaign | Header shows objective, channels, dates and utm_campaign; Spend 'of budget'; CTR = clicks/impressions %; CPC = spend/clicks; Collected from payments allocated to the invoices |
| Structure tab | Ad campaign > ad set > creative under the campaign, plus one creative with no ad set | Open Structure | Tree: campaign > ad campaign (platform chip, 'Lead form' chip if lead campaign, status, Daily budget) > ad set > creatives; the loose creative shown at level 1 |
| Leads tab | 2 attributed CRM leads, one became an order and invoice | Open Leads tab; click a row | Columns Date, Lead, Title, Source, Ad, Status, Quotes, Orders, Invoices, Revenue, Gross profit, Collected; row opens /crm/leads/<no> or /crm/pipeline/<no> |
| Delivery tab | Delivery rows on 3 days | Open Delivery | Daily spend bars (last 30 days) and an Entries table newest first |
| Revenue is read from posted invoices | Lead > quotation > order confirmed, invoice NOT posted | Open the campaign; then post the invoice and reopen | Before posting: Orders 1, Revenue 0. After posting: Revenue = invoice lines net (x fx rate), Gross profit = revenue - line cost |
| Journeys card | A journey with campaign set (API only - the builder has no campaign field) | Open Social-to-cash tab | 'Journeys on this campaign' lists it; otherwise 'None.' |
Ad Campaigns
| Action | When | What you do | What happens |
|---|---|---|---|
| Create an ad campaign | A campaign and an ad account | Ad Campaigns > New; name, Marketing campaign, Ad account, Platform Instagram, Objective Lead generation, Lead campaign ticked, Daily budget 500, Status Active; Save | Saved; shown in Ad Campaigns and in Lead Campaigns; appears in the campaign's Structure tab |
| Delete with children | An ad campaign that has an ad set | Open the ad campaign; Delete | Expected: a friendly refusal. Record what happens |
Lead Campaigns
| Action | When | What you do | What happens |
|---|---|---|---|
| Only lead campaigns listed | One ad campaign with and one without Lead campaign | Open Lead Campaigns | Only the ticked one is listed; the count matches |
| New from Lead Campaigns | Lead Campaigns > New; leave Lead campaign unticked; Save | Saved but it does NOT show on Lead Campaigns (the filter needs the tick) - tester note |
Ad Sets
| Action | When | What you do | What happens |
|---|---|---|---|
| Create an ad set | An ad campaign and an audience | Ad Sets > New; name, Ad campaign, Audience, Budget 3000, Status Active; Save | Saved; shown under its ad campaign in the campaign's Structure tab |
Creatives
| Action | When | What you do | What happens |
|---|---|---|---|
| Create a creative | An ad set | Creatives > New; name, Campaign, Ad set, Format Reel, Headline, CTA, Status; Save | Saved; shown under the ad set in the Structure tab |
Delivery & Spend
| Action | When | What you do | What happens |
|---|---|---|---|
| Enter a day of delivery | A campaign | Delivery > New; Date today, Campaign, Level Campaign, Spend 450.75, Impressions 12000, Clicks 340; Save | Saved; campaign record Spend +450.75, CTR 2.8%, CPC 1.33 |
| One entry per day per item | FN-021 done | New row for the same day, campaign and level | Refused: 'That day is already entered for this item - edit it instead.' |
| No double counting across levels | Campaign-level spend 450 and ad-set-level spend 200 on the same day | Open the campaign record and Campaign ROI | Spend = 450 (only the campaign level is used when it exists) |
| Import CSV | CSV with 3 good rows (campaign codes) and 1 unknown campaign | Import CSV; choose the file | Message '3 added, 0 updated - Row 4: no campaign ...'; rows appear with Source Import; re-import = '0 added, 3 updated' |
| Import by utm_campaign | Campaign utm_campaign 'ramadan26' | Import a row with campaign = ramadan26 | Row lands on that campaign |
Ad Accounts
| Action | When | What you do | What happens |
|---|---|---|---|
| Create an ad account | marketing.campaign.edit AND marketing.configure | Ad Accounts > New; Platform Facebook, Name, Account id, Pixel id, token (sandbox), Status Manual entry; Save | Saved; reopened record shows the token box empty (sealed); list has no token column |
| Delete only deactivates | An ad account | Open it; Delete | Record stays in the list with Active unticked (not removed); audience sync and conversions no longer use it |
Audiences
| Action | When | What you do | What happens |
|---|---|---|---|
| Create a dynamic audience | Test customers with posted invoices | Audiences > New; name, Type Dynamic, Purpose Marketing, Rule {"base":"customers","channel":"whatsapp"}; Save | Saved and built at once: Members = active customers, Reachable = those opted in on WhatsApp for Marketing; Status ready |
| Each rule base | Data for each case | Create one audience per base: leads, inactive_customers (days 30), high_value (min_value 20000), by_product, by_industry, by_location (city Dubai), abandoned_quotations (days 14), repeat_customers (min_orders 2) | Members match the rule (spot-check 2 per audience against Sales/CRM); leads excludes 'do not contact' and archived leads |
| Reachable counts only consented | Audience of 3: A opted in, B opted out, C no record | Open the audience | '1 of 3 reachable (consented)'; chips: A 'Opted in', B 'Opted out', C 'No consent recorded' |
| Unknown allowed by setting | FN-033; Settings 'Treat unknown consent as allowed' ticked | Rebuild the audience | C now 'Unknown - allowed by company setting'; 2 of 3 reachable. Untick again afterwards |
Audience record
| Action | When | What you do | What happens |
|---|---|---|---|
| Rebuild | Dynamic audience; add a new customer in Sales | Rebuild | Members +1; Audit 'marketing.audience.built' |
| Add member to a static audience | Static audience | Add member: name, phone +971501112233; Add | Member listed (key = 971501112233); Members +1; adding the same phone again does not duplicate |
| Remove member | Static audience with 2 members | Click the bin on one | Removed; Members and Reachable recounted |
| Sync without an ad account | No active ad account for TikTok | Platform tiktok; Sync audience | Refused: 'Connect an ad account on that platform first (Campaigns > Ad Accounts).' |
| Sync prepared (manual account) | Facebook ad account, status Manual entry | Platform facebook; Sync audience | Line shows 'facebook: prepared <count> <time>'; count = members with consent for Profiling or Marketing on 'Any channel'; hashes only (SHA-256), nothing sent |
| Real sync to Meta | Meta sandbox ad account with Status Connected and a test token | Sync audience to facebook | Status uploaded with external id, or failed with error. Blocked if no Meta sandbox account |
Consent
| Action | When | What you do | What happens |
|---|---|---|---|
| Record an opt-in | marketing.consent.edit | Record consent: phone +971501234567, WhatsApp, Marketing, Opted in, Explicit, source, evidence; Save | Row listed: Status Opted in, Consent date now, Expires = now + 720 days (24 months x 30 days); History shows one 'opted_in' entry by you |
| Opt-out wins | FN-042 done | Record consent for the same phone, WhatsApp, Marketing, Opted out | Same row moves to Opted out (not a second row); Opt-out date set; History has 2 entries; consent check answers 'Opted out' |
| 'Any channel' opt-out blocks every channel | Person opted in on WhatsApp | Record Opted out on 'Any channel' for Marketing; check WhatsApp and Email | Both refused 'Opted out' (opt-out on any channel wins over a WhatsApp opt-in) |
| Purpose is separate | Person opted out of Marketing on WhatsApp | Check Promotions on WhatsApp (API /consent/check?channel=whatsapp&purpose=promotions) | 'No consent recorded' (purposes are separate records). Transactional / Support always 'Service message' |
| Expiry | Settings 'Consent expires after' = 1 month | Record an opt-in; move the test clock or set expires_at to yesterday in a test database; reopen Consent | After expiry: Status column 'expired', Expired tab counts it, consent check 'Consent expired' |
| Never expires | Settings expiry 0 | Record an opt-in | Expires empty |
| Tabs, channel filter, search | Mix of records | Click each tab; choose Channel Email; search by part of a phone '5012' | Rows filter correctly; phone search matches digits. Note: tab counts are counted on the filtered list |
| STOP keyword (Omnichannel) | Omnichannel WhatsApp sandbox; contact opted in | Customer sends 'STOP' (or 'إلغاء', 'unsubscribe') | Opted out on WhatsApp for Marketing, Promotions and Newsletter, source 'whatsapp keyword', evidence = message; rules/journeys on 'Consent opted out' run. Blocked without a WhatsApp sandbox |
| START keyword | FN-049 done | Customer sends 'START' | Opted in on WhatsApp for Marketing (explicit) - other purposes stay opted out |
| History modal | A record with 3 changes | Click the History icon | When, Status, Source, Evidence, By - newest first; 'Current evidence' card |
Rules
| Action | When | What you do | What happens |
|---|---|---|---|
| Create a rule (draft) | New rule: name, When Lead created, condition Source contains Instagram, action Add tag 'ig'; Save | Saved with status draft; it does NOT run until activated | |
| Activate and fire | FN-052; scheduler on | Activate; create a CRM lead with Source 'Instagram Lead Ads'; wait for the scan (up to 10 min) or Settings > Scan ERP events now | Lead gets tag 'ig'; rule Runs +1, Last run set; Scheduled Actions > What ran shows 'Add tag ... done' |
| Conditions not met | Active rule FN-053 | Create a lead with Source 'Website' | No tag; Runs unchanged |
| any / all match | Rule with 2 conditions | Switch 'Conditions must' between all and any; trigger with one condition true | all: not run; any: run |
| Order and Stop | Rule A order 5 with Stop ticked, rule B order 10, same trigger | Fire the trigger | Only A runs; untick Stop -> A then B |
| Pause | Active rule | Pause; fire the trigger | Rule does not run; button shows Activate |
| Each Marketing action | A lead with an owner | One rule per action: Create CRM task, Assign lead owner (round robin), Set priority, Notify salesperson, Send email, Add to audience | Task due today + days on the owner; owner changed with CRM event 'Assigned by automation'; priority set; HR notification to owner; email sent only if Email consent; member added - each logged in Scheduled Actions |
| Omnichannel actions without Omnichannel | Omnichannel uninstalled | Rule with 'Send WhatsApp' fires | Logged 'skipped: Omnichannel is not installed'; Triggers card says Omnichannel actions run only while it is installed |
| Delete a rule | Rule with run history | Open; Delete | Rule gone; its log rows stay with Rule blank |
| Time triggers (daily) | Posted unpaid invoice due in 2 days; one overdue; a customer with last sale > inactive days | Active rules on Invoice due / Invoice overdue / Customer inactive; wait for the daily run | Each fires once per invoice (due: once per due date) and once per customer per last-sale date; Conversion Tracking does not list these (timed events) |
Journey builder
| Action | When | What you do | What happens |
|---|---|---|---|
| Build and save | New journey; name; trigger Lead created; Add step Action (Add tag); Wait 2 minutes; Condition 'Customer replied since the wait is set'; Yes: Stop; No: Action Notify salesperson; Save | 'Saved'; Test / Activate / Archive buttons appear; status draft | |
| Activate needs steps | A journey saved by API without nodes | Activate | Refused 'Add the steps before activating the journey.' |
| Test run | FN-061 | Test; deal_id of a test lead; Run once | Run status 'waiting' after the tag step; trail trigger > action; Recent runs shows it with 'wakes' time |
| Wait wakes | FN-063; scheduler on (A2N_SCHEDULER not 0) | Wait 2-3 minutes; reopen the journey | Run moved past the wait: condition 'no' -> notify; status completed. Scheduled Actions 'Waiting to run' is empty for it |
| Reply ends the wait early | Omnichannel; wait 1 day with 'or until the customer replies' | Customer replies on WhatsApp | Run wakes within a minute; condition 'Customer replied' = yes path. Blocked without Omnichannel sandbox |
| A/B branch | Branch 70/30 with a tag on each side | Run 20 tests | Roughly 14 A / 6 B (random) - each run's note says A or B |
| Re-entry | Active journey, re-entry off | Fire the trigger twice for the same lead | Only one run; tick Allow re-entry -> second run starts |
| Loop guard | A step whose next step points back (API) | Run | Stops after 60 steps: status failed, trail 'too many steps (a loop?)' |
| Pause and archive | Journey with a waiting run | Pause -> wait past wake time -> Activate; then Archive | Paused: run does not move; after Activate it continues. Archive: waiting runs become 'stopped' |
Triggers
| Action | When | What you do | What happens |
|---|---|---|---|
| Usage counts | 2 rules and 1 journey on Lead created (1 rule active) | Open Triggers | Lead created: Rules 2, Active rules 1, Journeys 1; Code column shows lead_created |
Scheduled Actions
| Action | When | What you do | What happens |
|---|---|---|---|
| Waiting and log | Runs waiting; actions run | Open Scheduled Actions | Waiting list ordered by Runs at; What ran shows rule/journey, event, action, status done/skipped/failed and detail |
Campaign ROI
| Action | When | What you do | What happens |
|---|---|---|---|
| Row maths | Campaign: spend 1,000; 10 leads (4 qualified, 2 opportunities); 1 order; invoice net 5,000 AED, line cost 3,000 | Open Campaign ROI | CPL 100.00; Cost per Opportunity 500.00; Cost per Order 1000.00; Revenue 5000.00; Gross Profit 2000.00; ROAS 5.00; Profit ROAS 2.00 |
| Totals and export | 3 campaigns | Check the total tiles; Export | Totals = sums; ROAS total = total revenue / total spend; CSV has every column |
| Date filter | Delivery and leads in Sep and Oct | From 2026-10-01 To 2026-10-31 | Only October spend and October leads counted |
| Attribution model changes credit | One lead touched by campaign A first, then campaign B | Settings model First touch -> ROI; Last touch -> ROI; Linear -> ROI | First: A gets 1 lead; Last: B gets 1; Linear: A 0.5 and B 0.5 (counts show 0.5, never 0.50). Revenue split the same way |
| Foreign-currency invoice | Attributed order invoiced in USD with fx rate 3.6725 | Open ROI | Revenue in AED = USD net x 3.6725 |
| Revenue only after posting | Order confirmed and invoiced but invoice draft | Open ROI; post the invoice; reopen | Revenue 0 before, invoice net after; Collected follows allocated payments |
Attribution
| Action | When | What you do | What happens |
|---|---|---|---|
| Lead from Omnichannel Leads | Omnichannel installed; campaign with utm_campaign 'ramadan26' | Omnichannel > Leads > Lead Inbox > Add lead (name, phone +971501234567, utm_campaign ramadan26); convert to a CRM lead; open Attribution | Row: Source, Platform, Campaign = the Ramadan campaign, UTM shown, Touches 1; CRM lead's Campaign field filled |
| Touches and last touch | Same lead touched again by another campaign (second conversation / form) | Open Attribution | Touches 2; first touch unchanged; campaign moves to the last touch |
| Lead without Omnichannel | Omnichannel not installed; create a CRM lead with Campaign text = a campaign name | Open Attribution / ROI | No attribution row is made (attribution comes only from Omnichannel captures) - note; ROI leads stay 0 |
| Partner sales inside the window | Attributed lead converted outside CRM (no quotation link); customer buys 30 days later; window 180 | Open ROI | That sale and its invoice count for the campaign; a sale 200 days later does not |
Conversion Tracking
| Action | When | What you do | What happens |
|---|---|---|---|
| Events recorded once | New CRM lead, quotation, confirmed order, posted invoice, receipt | Settings > Scan ERP events now (twice) | First scan message 'N events, M journeys moved'; one event per record per type; second scan adds 0 |
| Tabs and counts | FN-083 | Click each tab | Counts match; timed events (invoice due/overdue, customer inactive) are not listed |
| No conversion API | Platform switch off in settings | Record events | Status recorded, Sent to empty |
| No ad account | facebook ticked; no active Facebook ad account (or no pixel id) | Lead attributed to facebook; scan | Status skipped; Sent to 'facebook: no_account' |
| Queued for a manual account | Facebook ad account with pixel id, Status Manual entry | Scan | Status queued (not sent) |
| Real dispatch | Meta / TikTok / Snapchat / LinkedIn sandbox account, status Connected, test token and pixel | Post an attributed invoice; scan | Status sent (or failed with code); platform test-events tool shows the event with hashed email/phone. Blocked if no sandbox. Note: with A2N_MKT_TRANSPORT=capture 'sent' means captured only |
Marketing Settings
| Action | When | What you do | What happens |
|---|---|---|---|
| Save settings | marketing.configure | Change model, window 90, expiry 12, inactive 60, high value 20000, tick facebook; Save | 'Saved'; reload shows the values; Audit 'marketing.settings.saved' |
| Validation | Window 4000; Save | 'Between 0 and 3650.' on the window field; nothing saved | |
| Scheduler | A2N_SCHEDULER not 0 on staging | Create a CRM lead; do nothing for 10-12 minutes; open Conversion Tracking | Lead Created event appears without pressing Scan (scan every 10 minutes, journey waits every minute, time triggers once a day; first run ~75 s after start) |
Features
| Action | When | What you do | What happens |
|---|---|---|---|
| Automation switched off | Company admin | Applications > Marketing > Features: Automation and journeys Off; open Marketing menu; try to save a rule by API | Automation group gone from the menu; save refused 409 'Automation and journeys is disabled for this company.'; existing rules still readable by API. Switch back On |
| Attribution switched off | Turn Attribution, conversions and ROI Off; open Analytics; press Scan ERP events now | Scan refused 409; ROI/Attribution screens still open. Switch back On |
Fields
| Action | When | What you do | What happens |
|---|---|---|---|
| Campaign field rules | Fields: End date Required, Description Hidden; open Campaigns > New | Description not shown; End marked required and Save without it refused; set back to Shown |
Omnichannel menu
| Action | When | What you do | What happens |
|---|---|---|---|
| Same screens from Omnichannel | Both apps installed | Open Omnichannel > Campaigns > Audiences, Conversion Tracking; Automation > Rules; Analytics > Campaign ROI; Configuration > Consent | Each opens the Marketing screen with breadcrumb 'Omnichannel / ...'; data identical to Marketing |
| Marketing not installed | Uninstall Marketing (test company) | Open those Omnichannel entries | 'Not installed' card: '<screen> belongs to the Marketing app, which this company has not installed.'; Marketing API answers refused. Reinstall afterwards |
AI assistant
| Action | When | What you do | What happens |
|---|---|---|---|
| Campaign ROI question | marketing.analytics.view; campaigns with data | Ask 'What is the ROI of CMP-0001?' then 'ROI of all campaigns' | Answer with spend, revenue, gross profit, ROAS, profit ROAS and the model, plus a table; unknown name -> 'No campaign matches "...".' |
| Consent question | marketing.consent.view; person opted out on WhatsApp | Ask 'May I send WhatsApp marketing to +971501234567?' | 'No - Opted out (whatsapp).'; without phone/email -> 'Give a phone number or an email.'; the assistant never changes data |
Uninstall
| Action | When | What you do | What happens |
|---|---|---|---|
| Marketing uninstalled | Test company | Administration > Apps: uninstall Marketing; call any /marketing/ URL; reinstall | Refused while uninstalled; data back after reinstall |