AI powered marketing automation: beyond email drips

TL;DR

Difficulty: Intermediate

A drip campaign sends the same emails on the same schedule to everyone. AI driven automation decides per customer.

  • Dynamic pricing: propose, check the proposal against an approval line, then clamp to margin, daily change and RRP limits.
  • Recommendations: combine history, browsing, context and timing, and cap each category so the list is not eight of one thing.
  • Churn prediction: a five point rise in retention can lift lifetime value by about a fifth, and clicks beat opens as a signal since Apple Mail Privacy Protection.
  • Campaign agents: customer list audiences need 100 active users on Google, and targeting needs 90 days of history and over $50,000 of spend.
  • Rules: consent, or the 12 month exception for your own customers, for marketing email, the right to object, and the GDPR's Article 22 limits on significant automated decisions.

Most marketing automation in 2026 is still a flowchart with a mailing list. I show what changes when models make the decisions instead, across pricing, recommendations, churn and campaign budgets, with the guardrails, the arithmetic and the Irish and EU data protection rules each one needs, worked through on an invented Galway outdoor shop.

A drip campaign is a timer with a mailing list

Here is what marketing automation looks like at most eCommerce businesses in 2026. Someone signs up and gets a welcome email. Three days later, an email about bestsellers. A week later, a discount code. If they buy, they enter the post purchase sequence. If not, three more nudges and they are marked inactive.

That is a drip campaign. It was a big step forward ten years ago. Today it is a flowchart pretending to be intelligence. The emails go out on the same schedule whether the customer is a bargain hunter or a premium buyer. The recommendations are the same bestsellers for everyone. The timing is an arbitrary delay. And the discount code gives margin away to people who would have paid full price.

Much of what is now sold as "AI powered marketing automation" is the same flowchart with a language model writing the subject lines. That is not a transformation. That is a font change.

Real AI driven automation differs in four ways.

Predictive, not reactive. It estimates what a customer is likely to do and acts before they do it.

Individual, not bucketed. Traditional automation sorts people into "high value", "at risk" and "new subscriber". A model scores each customer on their own behaviour.

Continuous, not sequential. A drip has a start and an end. A model keeps scoring, learning and adjusting.

Learned, not hand written. Someone wrote every rule in your current automation: "if the basket is over €100, offer free delivery". A model learns which interventions work for which customers.

Worked example: the same welcome, two ways

Inagh Outdoor is an invented outdoor gear shop in Galway at inaghoutdoor.example, a short spin from the Connemara hills. Two people sign up on the same Monday. Sam browsed three €300 waterproof jackets for twenty minutes. Alex looked at the sale page for two minutes.

The drip sends both the same three emails: welcome on Monday, bestsellers on Thursday, 10% off the following Monday. Sam gets 10% off a jacket they were going to buy anyway, so Inagh gives away €30. Alex gets bestsellers at full price, which is the wrong page for a bargain hunter.

A scored approach sends Sam a jacket comparison on Tuesday, no discount, and Alex the end of season sale on Wednesday. Same tools, same email platform. The difference is that something decided, per person, what to send.

This article covers four places where that matters: pricing, recommendations, churn and campaign budgets. One caution before any of them. Email automation and ad audiences have their own plumbing and their own rules, which I take apart in triggering ads from email activity and a unified campaign automation stack. Everything below assumes that plumbing is sound.

Dynamic pricing needs guardrails before it needs a model

Dynamic pricing is the most powerful and most misunderstood use of AI in eCommerce. It is not surge pricing that squeezes customers at peak demand. Done properly, it finds a sound price for each product and adjusts it as demand, competition, stock and the season change.

The core idea is price elasticity: how much demand moves when price moves. Some products are elastic (customers switch over a 5% difference). Others are inelastic (people pay for convenience, trust or quality). Estimating elasticity well is a regression problem, worked through step by step in modelling demand and price elasticity. Foundations: elasticity

The model is the easy part. The governance is where most implementations fail. Without limits, a pricing algorithm can race a competitor to the bottom, make prices jump around until customers stop trusting them, or trade long term loyalty for a good week. So the engine's shape is: propose, check the proposal, then constrain.

class DynamicPricingEngine
  GUARDRAILS = {
    min_margin: 0.15,        # never below 15% margin on cost
    max_daily_change: 0.08,  # at most 8% a day
    max_above_rrp: 0.05,     # at most 5% above the recommended retail price
    approval_above: 0.15     # a proposal over 15% goes to a person
  }.freeze

  def reprice(variant)
    current = variant.price
    proposed = PriceModel.optimal_price(variant) # demand, stock, competitor prices, season
    change = ((proposed - current) / current).abs

    if change > GUARDRAILS[:approval_above]
      PricingApprovalQueue.enqueue(variant: variant, current: current, proposed: proposed)
    else
      new_price = constrain(variant, current, proposed)
      variant.update!(price: new_price)
      PricingLog.create!(variant: variant, current: current, proposed: proposed, applied: new_price)
    end
  end

  private

  def constrain(variant, current, proposed)
    step = current * GUARDRAILS[:max_daily_change]
    price = proposed.clamp(current - step, current + step)
    price = [price, variant.cost_price * (1 + GUARDRAILS[:min_margin])].max
    rrp = variant.recommended_retail_price # the shop's own field
    price = [price, rrp * (1 + GUARDRAILS[:max_above_rrp])].min if rrp
    price.round(2)
  end
end

The approval check looks at what the model wanted before anything clamps it. If the clamp came first, a large proposal would be cut to 8% and never reach the approval queue. Every decision is logged with what was proposed and what was applied.

Worked example: a jacket price on a quiet week

The example's figures: a Inagh jacket costs €150 to buy in, sells at €299, and the recommended retail price is €300.

The model proposes €279 because sales have slowed. The change is (299−279)÷299=6.7%(299 - 279) \div 299 = 6.7\%, under the 15% approval line, so the engine may act. The daily limit is 299×0.08=€23.92299 \times 0.08 = €23.92, so €279 is allowed. The margin floor is 150×1.15=€172.50150 \times 1.15 = €172.50, far below. The RRP ceiling is 300×1.05=€315300 \times 1.05 = €315, not reached. The price moves to €279.

Next week the model proposes €239. That is (279−239)÷279=14.3%(279 - 239) \div 279 = 14.3\%, still under 15%, so the engine acts, but the daily limit is 279×0.08=€22.32279 \times 0.08 = €22.32, so the price only moves to €256.68 today. If the model had proposed €229 (17.9%), a person would have seen it first.

Pricing on individual customer data adds a legal question. Under Article 22 of the GDPR a person has the right not to be subject to a decision based solely on automated processing that has legal or similarly significant effects on them. Such a decision is allowed only where it is necessary for a contract, authorised by law or based on explicit consent, and then needs safeguards: at least human intervention, a chance to give their point of view and a way to contest it.1 Whether an individual price is significant depends on the case. Pricing by product, stock and season, as above, avoids the question entirely.

The multi agent version of this problem, where several shops on the same optimisation platform compete on price, is one I'm working through in GrowCentric.ai. It needs collision detection and behaviour that seeks a stable outcome rather than a price war, and I wrote it up in when your AI starts fighting itself.

Recommendations that know what the customer is doing

Most shop recommendation engines say "customers who bought X also bought Y". That is collaborative filtering. It optimises for popularity, not relevance. It shows what most people bought, not what this person needs, and it ignores context: casual browsing on a Tuesday evening is not an urgent search on a Saturday morning.

Better recommendations combine several signals.

Purchase history says what someone bought and what usually comes next. Someone who bought a tent in April often needs a sleeping mat, a stove and pegs before the first trip.

Browsing behaviour shows intent. Five waterproof jackets viewed in the last hour is a different need from someone idly scrolling fleeces.

Session context matters. A visitor arriving from a Google Shopping advert for "men's waterproof jacket size L" wants jackets in large, not the homepage.

Timing predicts needs. A walking boot bought in October is due reproofing wax by spring.

There is also evidence that it pays. BCG reported in 2024 that the revenue growth of retail personalisation leaders is 10 percentage points higher than that of retailers that lag, and that personalised recommendations can drive 10 to 20 percentage points of cross sell for retailers selling across several categories.2

In a Solidus shop, the engine generates candidates from several sources, scores them, then makes sure the list is not eight versions of the same thing:

class RecommendationEngine
  MAX_PER_CATEGORY = 3

  def recommendations_for(user, context:, limit: 8)
    candidates = [
      CollaborativeCandidates.for(user),
      ContentCandidates.for(user),
      NextPurchaseCandidates.for(user),
      ContextCandidates.for(context)
    ].flatten.uniq(&:id)

    scored = candidates.map { |product| [product, RelevanceModel.score(user, product, context)] }
    diversify(scored.sort_by { |_, score| -score }.map(&:first), limit)
  end

  private

  def diversify(ranked, limit)
    per_category = Hash.new(0)
    ranked.each_with_object([]) do |product, chosen|
      category = product.taxons.first&.id
      next if per_category[category] >= MAX_PER_CATEGORY

      chosen << product
      per_category[category] += 1
      break chosen if chosen.size >= limit
    end
  end
end

The diversity rule is subtle and important. It caps each category at three. Without it, someone who looked at waterproof jackets is shown eight waterproof jackets.

Worked example: diversifying Sam's list

The model's top ten for Sam, in score order, are seven jackets, then gaiters, reproofing wash and a head torch. Without the cap, the eight slots are seven jackets and the gaiters.

With a cap of three per category, the engine takes the first three jackets, skips jackets four to seven, then takes the gaiters, the reproofing wash and the head torch. That is six products, so it carries on down the full candidate list and adds a thermal base layer and a dry bag, two more categories Sam had not searched but will want on a wet hill. Eight slots, six categories, and every item still scored highly.

Churn prediction: keep customers before they drift

Finding a new customer costs five to 25 times more than keeping one, depending on the study and the industry, and research by Frederick Reichheld of Bain and Company found that raising retention by 5% raises profits by 25% to 95%.3 Yet most shops only notice churn after it has happened, when someone simply stops buying.

The reason retention moves profit so much is visible in the lifetime value formula:

CLV=M×r1+d−rCLV = M \times \frac{r}{1 + d - r}

Here CLVCLV is the customer's lifetime value, MM is the margin per customer per year, rr is the retention rate (the share of customers who buy again next year) and dd is the discount rate that makes future money worth less than money today. Because rr sits in the denominator too, a small rise in retention has an outsized effect. Foundations: lifetime value

Worked example: five points of retention at Inagh

The example's figures: a Inagh customer brings €60 of margin a year, 60% buy again the next year, and the discount rate is 10%.

CLV=60×0.601+0.10−0.60=60×1.2=72CLV = 60 \times \frac{0.60}{1 + 0.10 - 0.60} = 60 \times 1.2 = 72

So CLVCLV is €72 per customer. Raise rr to 0.65:

CLV=60×0.651+0.10−0.65=60×1.444=86.67CLV = 60 \times \frac{0.65}{1 + 0.10 - 0.65} = 60 \times 1.444 = 86.67

With r=0.65r = 0.65, CLVCLV is €86.67. Five points of retention lift each customer's value from €72 to €86.67, about 20%, with no new customers at all. That is the case for churn prediction in one line.

How a churn model sees the signals

The signals are usually in data you already have: longer gaps between orders, smaller baskets, fewer visits, visits that only check order status, unhappy support tickets, unsubscribing from some lists but not others. No single signal means much. A model that weighs them together can rank customers by risk.

One signal to treat with care is the email open. Apple's Mail Privacy Protection downloads remote content, including the invisible image that records an open, in the background by default, whether or not anyone reads the message.4 For a large share of readers, a falling open rate tells you about their mail settings, not their loyalty. Clicks and site visits are what a person actually did. I go into this in triggering ads from email activity.

class ChurnPredictionJob < ApplicationJob
  RISK_THRESHOLD = 0.7

  def perform
    Spree.user_class.joins(:orders).merge(Spree::Order.complete).distinct.find_each do |user|
      risk = ChurnModel.predict(features_for(user))
      next if risk < RISK_THRESHOLD

      intervention = choose_intervention(user, risk)
      deliver(user, intervention)
      AgentAuditLog.create!(agent_name: "Churn", action_type: intervention, decision_payload: { user_id: user.id, risk: risk })
    end
  end

  private

  def features_for(user)
    orders = user.orders.complete
    {
      days_since_last_order: (Date.current - orders.maximum(:completed_at).to_date).to_i,
      orders_last_365_days: orders.where(completed_at: 365.days.ago..).count,
      email_clicks_90_days: EmailEngagement.clicks(user, since: 90.days.ago), # clicks, not opens
      site_visits_30_days: VisitLog.count_for(user, since: 30.days.ago),     # consented analytics only
      open_support_tickets: SupportTicket.open.where(user: user).count,
      lifetime_margin: CustomerMargin.lifetime(user)
    }
  end

  def choose_intervention(user, risk)
    return :personal_call if CustomerMargin.lifetime(user) > 500 && risk > 0.85
    return :feedback_request unless user.email_marketing_permitted? # the shop's own consent record
    :personalised_offer
  end

  def deliver(user, intervention)
    case intervention
    when :personal_call then CustomerCareNotifier.flag(user)
    when :feedback_request then ServiceMailer.feedback_request(user).deliver_later
    when :personalised_offer then RetentionMailer.offer(user, NextPurchase.for(user)).deliver_later
    end
  end
end

The intervention choice is the important part. Not every at risk customer needs a discount. Some need a problem solved, some a reminder of what they liked, and a high value customer may deserve a phone call. And a marketing email, offer or not, needs the right permission: under regulation 13 of the ePrivacy Regulations 2011, marketing email to an individual needs their consent, or, for your own customers, the exception in regulation 13(11). That exception covers your own products of a kind similar to what they bought, needs an easy and free way to object when you took the address and in every message since, and runs out 12 months after the sale unless you have emailed them under it within that time.5 The Data Protection Commission has looked at a feedback email. An airline asked a passenger about a recent trip, and the DPC said correspondence "sent solely for informational or feedback purposes does not constitute direct marketing", while one with marketing content would be, and would need an unsubscribe option.6 That email passed because it only sought feedback to improve the service. The code above sends :feedback_request to exactly the customers without marketing permission, and sends it to win them back. That only holds if the email is plain questions about the order, with no offer, no product and no request for a review to promote the shop. The safer course is to send it only to people who allowed marketing or fall under the regulation 13(11) exception.

Worked example: is a retention offer worth it?

The example's assumptions: the model flags 400 Inagh customers a month above 0.7 risk. Without action, 50% of them would not buy again. A €10 voucher brings 15% of the would be leavers back, and each returning customer is worth the €72 lifetime value from above. Every flagged customer who uses the voucher costs €10, and the example assumes 30% of the 400 use it, including some who would have stayed anyway.

Customers saved: 400×0.5×0.15=30400 \times 0.5 \times 0.15 = 30. Value saved: 30×72=€2,16030 \times 72 = €2{,}160. Voucher cost: 400×0.30×10=€1,200400 \times 0.30 \times 10 = €1{,}200. Net: 2,160−1,200=€9602{,}160 - 1{,}200 = €960 a month. Positive, fair enough, but the voucher eats more than half the gain, which is why a feedback request or a well chosen recommendation, which costs nothing, should be tried first on the lower risk group. Foundations: expected value

How GrowCentric.ai ties it together

Pricing, recommendations, churn and campaign management are not separate systems in GrowCentric.ai. They are specialised agents in a coordinated multi agent system.

The analytics agent monitors the marketing channels, tracks performance, spots anomalies (a sudden cost spike, a conversion drop, a budget overrun) and raises insights that would take an analyst hours or days.

The budget allocation agent acts on them. It moves spend from weaker campaigns to stronger ones, respects daily and monthly caps, and allows for diminishing returns: doubling spend does not double results, and the agent looks for the point where each channel flattens. Foundations: marginal versus average

The audience agent analyses behaviour and builds segments. Instead of broad demographics ("women aged 25 to 34 in Galway"), it looks for behavioural clusters: people who research for a long time before buying, price sensitive comparison shoppers, loyal repeat buyers, seasonal buyers.

The conflict resolution agent handles the problem unique to a platform with competing clients. When two clients sell similar products to similar audiences, their agents can bid against each other without knowing it and push up costs for both. This agent detects the collisions, segments to reduce the overlap and uses game theory to look for outcomes that work for both.

The agents talk through a shared event bus. When the analytics agent sees a campaign's cost per acquisition spike, it fires an event. The budget agent reduces spend, the audience agent checks whether the audience is contested and proposes alternatives, and the conflict agent checks whether a client collision is the cause. All of it runs on Rails, with ActiveSupport::Notifications for events, Sidekiq for background work, a full API, and human approval for high risk decisions.

Audiences built from customer lists meet the ad platforms' own rules. On Google, a customer list needs at least 100 active users before it is used on the Display, Search or YouTube networks,7 and using lists for targeting needs 90 days of account history and more than $50,000 of lifetime spend, while any account in good standing can use them for exclusions.8 And every upload rests on a lawful basis and the customer's choices, recorded on the customer record, as I set out in a unified campaign automation stack.

Worked example: is Inagh's segment big enough?

The audience agent finds a promising cluster: 180 customers who bought boots last autumn and have not bought since. Inagh's email list matches Google accounts at an assumed 45%, so about 180×0.45=81180 \times 0.45 = 81 people would match. That is under 100, so Google will not use the list. And Inagh's Google account has spent €18,000 to date, well under the targeting threshold, so the list could only be used as an exclusion anyway. The right channel for this segment is an email to those who have given permission, not an advert.

A practical path for a Solidus shop

If you run a shop on Solidus, here is the path from drips to automation that decides.

Phase 1: get the data right. Audit product data, deduplicate customers, fix stock accuracy and make event tracking consistent, as in how to integrate AI into your existing workflows. Nothing above works on dirty data.

Phase 2: publish lifecycle events. Solidus already publishes events such as order_finalized on Spree::Bus, and you can register your own for product views, baskets and returns.9 That is the perception layer every model reads from.

Phase 3: start with recommendations. They have the clearest return and the lowest risk. Measure the extra revenue from recommended products against a group that sees the old list.

Phase 4: add churn prediction. Start with alerts only, flagging at risk customers for a person, then move to automatic interventions by customer value.

Phase 5: try dynamic pricing carefully. It needs the most governance. Start with one category, strict guardrails, and measure both revenue and customer trust. Never without a person able to stop it.

Phase 6: automate campaigns. Once the shop's data and events are clean, a layer such as GrowCentric.ai can manage campaigns, budgets and audiences without someone watching dashboards all day.

Compliance is architecture

Pricing, recommendations and churn models all process personal data, and some make automated decisions about customers. In Ireland that means the GDPR and the ePrivacy Regulations 2011, both enforced by the Data Protection Commission (DPC). The 2011 Regulations still name the Data Protection Commissioner, and the Data Protection Act 2018 transferred all of the Commissioner's functions to the Commission.10 And because Ireland is in the EU, the Cyber Resilience Act and the NIS2 Directive add duties on security and incident reporting.

Customers have an absolute right to object to direct marketing, and once they do, their data must not be used for it.11 Models need to be explainable enough that you can say why a customer was flagged or why a product was recommended, both for the safeguards above and because a model nobody can explain is a model nobody trusts.

Everything I build, for GrowCentric.ai or for clients, includes audit logs, GDPR compliant data processing, transparency about how decisions are made and a human override. Compliance is not an afterthought. It is architecture.

The bottom line

Marketing automation should decide, not just schedule. The tools exist to price on real demand, recommend from real behaviour, spot customers drifting away and manage campaigns continuously.

Most businesses use none of it. They run the same drips with better subject lines. That is an opening for anyone willing to do the real work: clean the data, build the events, add one model at a time, and keep the guardrails on.

Footnotes

  1. Regulation (EU) 2016/679 (General Data Protection Regulation), Article 22, automated individual decision making, including profiling, EUR-Lex, https://eur-lex.europa.eu/legal-content/EN/TXT/HTML/?uri=CELEX:32016R0679

  2. Mark Abraham and others, Retail spotlight: personalization in action, Boston Consulting Group, 18 November 2024, https://www.bcg.com/publications/2024/personalization-in-action

  3. Amy Gallo, The value of keeping the right customers, Harvard Business Review, 29 October 2014, https://hbr.org/2014/10/the-value-of-keeping-the-right-customers

  4. Apple, Mail Privacy Protection and privacy, Apple Legal, https://www.apple.com/legal/privacy/data/en/mail-privacy-protection/

  5. European Communities (Electronic Communications Networks and Services) (Privacy and Electronic Communications) Regulations 2011, S.I. No. 336 of 2011, regulation 13(1) and (11), Irish Statute Book, 2011, https://www.irishstatutebook.ie/eli/2011/si/336/made/en/print

  6. Data Protection Commission, Direct Marketing, case study on an airline feedback email, dataprotection.ie, https://www.dataprotection.ie/en/dpc-guidance/case-studies/electronic-direct-marketing/direct-marketing

  7. Google, About audience segments in Audience manager, Google Ads Help, 2026, https://support.google.com/google-ads/answer/7558048

  8. Google, Customer Match policy, Google Ads Help, 2026, https://support.google.com/google-ads/answer/6299717

  9. Solidus Guides, Subscribing to events, accessed November 2026, https://guides.solidus.io/customization/subscribing-to-events

  10. Data Protection Act 2018, section 14, transfer of functions of Data Protection Commissioner to Commission, Irish Statute Book, 2018, https://www.irishstatutebook.ie/eli/2018/act/7/enacted/en/print

  11. Regulation (EU) 2016/679 (General Data Protection Regulation), Article 21(2) and (3), right to object, EUR-Lex, https://eur-lex.europa.eu/legal-content/EN/TXT/HTML/?uri=CELEX:32016R0679

If your automation is still a set of timers, bring your email flows and a year of orders to the free workshop and we will find the one decision a model should take over first. The first two weeks of work are on me.