Skip to content
Rapcsány Krisztián Rapcsány Krisztián
hu
← All projects Data-driven marketing automation

Statistics, SEO and email campaign system

The measuring and campaign system that goes with the platform. It measures visitors and revenue, watches SEO, and sends part of the email campaigns by itself. Most of the code is defensive: it is about not sending the wrong email to the wrong person.

PHP Laravel 12 Redis Message queues Web analytics SEO automation Email and push
The challenge
My role

I designed and built it, from data collection to campaign logic.

For a ticketing business, marketing and search traffic decide how many people reach a purchase. The manual work, meaning reports, campaign emails and SEO checks, is slow and is rarely finished on time.

I wanted to bring measurement, SEO monitoring and campaign sending into one place. Routine work should run by itself, but without harming subscribers or the reputation of the email.

The solution
01

Event statistics and revenue

Sales and arrival charts per event, revenue by ticket type, conversion analysis, referral and loyalty metrics, with exportable reports.

02

In-house web analytics

Live active visitors, page views, source breakdown, checkout funnel, heatmaps, click and scroll analysis and session replay.

03

SEO automation

Daily error monitoring, weekly performance checks on key pages, search data import and a weekly report with alerts, automatic sitemaps and indexing notifications.

04

Campaign emails

Abandoned-cart reminders in two steps, win-back emails for lapsed buyers, pre-event recommendations to ticket holders, post-event rating requests.

05

Personalised recommendations

A weekly recommendation by email or push, built from events scored by the user's city, music taste and friends.

06

Marketing drafts

Post and ad drafts are generated from upcoming events and wait for approval: the system never posts or spends on its own.

Screenshots
From sign-up to purchase

The conversion funnel step by step, broken down by traffic source and profile. Guest names and email addresses are cropped out.

With brand and customer names and personal data removed (except the app store screenshots).

What makes it special

It does not post and does not spend

From upcoming events it prepares post and ad drafts, but they wait for approval. For ad spend it only gives a suggestion.

Personalised recommendations

The weekly recommendation scores events by the user's city, music taste and friends, and goes out by email or push.

I measure with a control group

I measure a campaign's real effect by giving a control group a calculated recommendation without sending it. That shows what the sending actually brought.

Challenges I ran into
01

Do not send the wrong email

Every campaign has a switch, a dry run with no sending, a recipient limit per run, a cool-down for the same recipient, a suppression list and a shared weekly cap. The win-back email, for example, is off by default and goes to at most 150 recipients per run.

02

Why did they not get an email?

The sending rule does not return the first reason for skipping, it returns all of them. So in a preview I can see exactly why someone dropped off the list.

03

Analytics must not bloat the database

I aggregate raw visitor events every minute, build daily summaries, and only delete the raw rows after the summary. The history stays, but the table does not grow forever.

Under the hood

Protected campaign sending

A switch for each campaign, dry runs with no sending, batch limits, cool-down against repeat sends, a suppression list and a shared weekly cap, so email reputation and subscriber trust are not damaged.

Measurable impact

Opens, clicks and purchases per email type, A/B variant assignment and measuring a campaign's real effect (uplift), so it is results, not just sends.

Analytics without the load

Raw visitor events are aggregated every minute into permanent daily summaries, and raw rows are only deleted after rollup, so history is kept while the database stays lean.

Re-runnable data imports

Syncs from external data sources can be re-run, and reloading a day overwrites the old data, so statistics stay clean after an error or outage.

Real code

Sending rules, with explanations

Every recommendation passes through this decision point. It returns all reasons for skipping, not just the first, so a preview shows exactly why someone does not receive an email.

RecommendationPolicy.php
public function evaluate(User $user, string $channel, ?CarbonInterface $now = null): PolicyDecision
{
    $now = ($now ?? Carbon::now())->copy();
    $reasons = []; // collect ALL reasons, not just the first, so a preview can explain every skip

    if (! (bool) $this->cfg('enabled', false)) {
        $reasons[] = 'kill_switch_off';
    }

    if ($user->is_banned || $user->deleted_at) {
        $reasons[] = 'account_blocked';
    }

    if ($channel === self::CHANNEL_EMAIL) {
        if (! (bool) $user->is_subscribed) {
            $reasons[] = 'no_marketing_consent';
        }
        if ($this->emailSuppressed(trim((string) $user->email))) {
            $reasons[] = 'email_suppressed';
        }
    } elseif ($channel === self::CHANNEL_PUSH) {
        if ($this->isQuietHour($now)) {
            $reasons[] = 'quiet_hours';
        }
    }

    // ... weekly cap from the shared marketing ledger, then the holdout control group
}
Result

Measurement, SEO monitoring and campaigns run from one place and mostly on their own. I can see what brings visitors and buyers, and wherever there is cost or risk, a human still approves.

Would you measure, monitor SEO or automate campaigns?

I can help you put together a system that measures what works and protects your subscribers.

More projects

Get a quote →