turnley.dev

PHP and MySQL code for faucet operators

Tools & Calculators

ADS-008

A surf engine that cycles a visitor through sites

Server-held session state, one destination at a time, dwell enforced on the server. The core of a traffic exchange in one table and two functions.

A surf session is a small state machine: pick the next destination, show it, wait, credit, repeat until the cycle ends. Keeping that state in the browser makes every part of it editable by the visitor.

Hold it server-side and the whole thing becomes tractable. The session row knows which destinations have been served, how many remain and when the current one started. The page just renders whatever the server says is next.

Excluding the surfer's own sites matters more than it looks. Nothing destroys trust in an exchange faster than seeing your own page in your own rotation.

PHP
function start_session(PDO $pdo, int $surferId, string $visitorKey, int $cycleLength = 10): int
{
    $pdo->prepare(
        'INSERT INTO surf_sessions (surfer_id, visitor_key, remaining, started_at)
         VALUES (?, ?, ?, NOW())'
    )->execute([$surferId, $visitorKey, $cycleLength]);

    return (int) $pdo->lastInsertId();
}

function next_destination(PDO $pdo, int $sessionId, int $surferId): ?array
{
    $st = $pdo->prepare(
        'SELECT s.*
         FROM surf_sites s
         WHERE s.active = 1
           AND s.verified = 1
           AND s.credits > 0
           AND s.owner_id <> ?                                  -- never their own site
           AND s.id NOT IN (
                 SELECT site_id FROM surf_views WHERE session_id = ?   -- not twice in a cycle
           )
         ORDER BY s.weight DESC, RAND()
         LIMIT 1'
    );
    $st->execute([$surferId, $sessionId]);
    $site = $st->fetch(PDO::FETCH_ASSOC);
    if (!$site) {
        return null;                                             // nothing left to show
    }

    $pdo->prepare('UPDATE surf_sessions SET current_site_id = ?, current_started_at = NOW() WHERE id = ?')
        ->execute([$site['id'], $sessionId]);

    return $site;
}

Using it

Weight the ordering by whatever the site owner spent. That is the whole product: paying more means being seen sooner and more often.

End the cycle explicitly and show a summary. A surf loop with no visible end is exhausting and people stop before they earn anything.

What bites people

Exclude sites already shown in this session, or a thin inventory will loop the same three pages and the advertiser pays for one visitor over and over.

RAND() ordering is fine at a few thousand rows. Past that, sample a random id range first.

Frame-busting sites will escape your surf bar. Detect it and skip that site rather than losing the session.

This one touches real money. Point it at a throwaway wallet and watch a full cycle before you trust it with a live balance.

Also in Ads, Traffic and Offerwalls