1. Install the SDK
Run this from your WordPress root (the folder containing wp-config.php):
composer require rudderstack/rudder-php-sdk |
|---|
That's it. Composer creates a vendor/ folder with the SDK inside.
No Composer access? Download the SDK as a ZIP from https://github.com/rudderlabs/rudder-php-sdk, unzip it, and place the folder inside your plugin directory. Then load it with require_once. |
|---|
2. Add Your Credentials
Open wp-config.php and add these two lines before /* That's all, stop editing! */:
define( 'RUDDER_WRITE_KEY', 'YOUR_WRITE_KEY_HERE' ); define( 'RUDDER_DATA_PLANE_URL', 'https://your-dataplane.rudderstack.com' ); |
|---|
Keep secrets out of version control. If you use a .env file or server environment variables: |
|---|
define( 'RUDDER_WRITE_KEY', getenv('RUDDER_WRITE_KEY') ); define( 'RUDDER_DATA_PLANE_URL', getenv('RUDDER_DATA_PLANE_URL') ); |
3. Create the Plugin
Create this folder and two files:
wp-content/plugins/rudderstack/ ├── rudderstack.php ← plugin entry point └── class-tracker.php ← tracker class |
|---|
rudderstack.php
<?php /** * Plugin Name: RudderStack Tracking * Description: Server-side event tracking via the RudderStack PHP SDK. * Version: 1.0.0 * Requires PHP: 7.4 */
if ( ! defined( 'ABSPATH' ) ) exit;
// Load Composer autoloader from WordPress root require_once ABSPATH . 'vendor/autoload.php';
// Load our tracker require_once __DIR__ . '/class-tracker.php';
// Boot RudderTracker::boot(); |
|---|
class-tracker.php
This is the only file you need to understand. It wraps the SDK and exposes three simple methods: page(), identify(), and track().
<?php
self::identify([ 'email' => $user->user_email, 'name' => $user->display_name, 'firstName' => $user->first_name, 'lastName' => $user->last_name, 'role' => implode( ', ', $user->roles ), ]);
self::track( 'Signed In', [ 'method' => 'wordpress' ] ); }
/** Fires when a new user registers. */ public static function on_register( int $user_id ): void { $user = get_userdata( $user_id );
self::identify([ 'email' => $user->user_email, 'name' => $user->display_name, 'createdAt' => $user->user_registered, ]);
self::track( 'Signed Up', [ 'method' => 'wordpress' ] ); }
/** Fires when a user logs out. */ public static function on_logout( int $user_id ): void { self::track( 'Signed Out' ); }
// ------------------------------------------------------------------------- // Helpers // -------------------------------------------------------------------------
/** WordPress user ID, or null if logged out. */ private static function user_id(): ?string { $id = get_current_user_id(); return $id ? 'wp_' . $id : null; }
/** * Anonymous ID stored in a first-party cookie. * Created on first visit, lasts 1 year. */ private static function anon_id(): string { if ( ! empty( $_COOKIE['rs_anon_id'] ) ) { return sanitize_text_field( $_COOKIE['rs_anon_id'] ); } $id = 'anon_' . bin2hex( random_bytes(8) ); setcookie( 'rs_anon_id', $id, time() + YEAR_IN_SECONDS, COOKIEPATH, COOKIE_DOMAIN, is_ssl(), true ); return $id; }
/** Current page URL. */ private static function current_url(): string { return ( is_ssl() ? 'https' : 'http' ) . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; }
/** Standard context block added to every event. */ private static function context(): array { return [ 'ip' => sanitize_text_field( $_SERVER['REMOTE_ADDR'] ?? '' ), 'userAgent' => $_SERVER['HTTP_USER_AGENT'] ?? '', 'page' => [ 'url' => self::current_url(), 'referrer' => $_SERVER['HTTP_REFERER'] ?? '', ], ]; } } |
|---|
Activate the plugin from wp-admin → Plugins. That's all the setup needed.
4. Track Page Views
Page views are tracked automatically — no extra code needed. Every front-end page load fires:
page( title, category, { url, title } )
To track a specific page with extra data, call it manually from a template or functions.php:
RudderTracker::page( 'Pricing', 'Marketing', [ 'plan_shown' => 'pro', ]); |
|---|
5. Identify Users
Users are identified automatically on login and registration via the built-in hooks.
To attach extra traits at any point (e.g. after a profile update):
RudderTracker::identify([ 'email' => '[email protected]', 'name' => 'Jane Smith', 'plan' => 'pro', 'company' => 'Acme Inc', ]); |
|---|
How identity stitching works: Before login a visitor has an anonymousId. When they log in, identify() links that anonymous history to their userId — giving you a complete picture of their journey. |
|---|
6. Track Custom Events
Call RudderTracker::track() anywhere in PHP — in a template, functions.php, a form handler, or a REST endpoint.
Examples:
// A button or CTA was clicked (triggered server-side on form POST) RudderTracker::track( 'Demo Requested', [ 'email' => sanitize_email( $_POST['email'] ), 'company' => sanitize_text_field( $_POST['company'] ), ]);
// A file was downloaded RudderTracker::track( 'File Downloaded', [ 'file_name' => 'annual-report-2026.pdf', 'file_type' => 'pdf', ]);
// A blog post was read if ( is_single() ) { RudderTracker::track( 'Article Read', [ 'post_id' => get_the_ID(), 'title' => get_the_title(), 'author' => get_the_author(), 'category' => implode( ', ', wp_list_pluck( get_the_category(), 'name' ) ), ]); }
// A contact form was submitted (Contact Form 7) add_action( 'wpcf7_mail_sent', function( $form ) { $data = WPCF7_Submission::get_instance()->get_posted_data();
RudderTracker::track( 'Form Submitted', [ 'form_name' => $form->title(), 'email' => sanitize_email( $data['your-email'] ?? '' ), ]); });
// A search was performed add_action( 'wp', function() { if ( is_search() && get_search_query() ) { RudderTracker::track( 'Search Performed', [ 'query' => get_search_query(), 'results' => (int) $GLOBALS['wp_query']->found_posts, ]); } }); |
|---|
The pattern is always the same: event name + properties array. Use any property names that make sense for your business.
7. Test It Works
Step 1 — Check your PHP error log
Add this to wp-config.php temporarily:
define( 'WP_DEBUG', true ); define( 'WP_DEBUG_LOG', true ); define( 'WP_DEBUG_DISPLAY', false ); |
|---|
Then add a one-line debug call anywhere:
add_action( 'wp', function() { RudderTracker::track( 'Test Event', [ 'source' => 'debug' ] ); }); |
|---|
Load any page and check wp-content/debug.log — you should see no PHP errors from the plugin.
Step 2 — Check RudderStack Live Events
Go to RudderStack Dashboard → Sources → your source → Live Events.
Load a page on your WordPress site. Within a few seconds the event appears:
{ "type": "page", "name": "Hello World", "anonymousId": "anon_3f8a...", "context": { "ip": "...", "userAgent": "..." } } |
|---|
Step 3 — Test via WP-CLI
wp eval ' RudderTracker::track("CLI Test", ["ts" => date("c")]); echo "Done — check Live Events\n"; ' |
|---|
8. Event Reference
What happened | Method | Example event name |
|---|---|---|
Page loaded | page() | (automatic) |
User logged in | identify() + track() | Signed In |
User registered | identify() + track() | Signed Up |
User logged out | track() | Signed Out |
Form submitted | track() | Form Submitted |
Search performed | track() | Search Performed |
File downloaded | track() | File Downloaded |
Article read | track() | Article Read |
Any custom action | track() | (your choice) |
9. Troubleshooting
Events not showing in Live Events
Double-check RUDDER_WRITE_KEY and RUDDER_DATA_PLANE_URL in wp-config.php
Make sure composer install was run and vendor/autoload.php exists
Enable WP_DEBUG_LOG and check wp-content/debug.log for PHP errors
vendor/autoload.php not found
cd /path/to/wordpress-root composer install |
|---|
Events fire on admin pages too
The auto_page_view method already skips is_admin(). If you add manual track() calls in functions.php, wrap them yourself:
if ( ! is_admin() ) { RudderTracker::track( 'My Event', [] ); } |
|---|
No Composer on managed hosting
Download the SDK ZIP from GitHub, place it in your plugin folder, and replace the autoloader line:
// Instead of: require_once ABSPATH . 'vendor/autoload.php'; require_once __DIR__ . '/rudder-php-sdk/lib/Rudder.php'; |
|---|
RudderStack PHP SDK docs: https://www.rudderstack.com/docs/sources/event-streams/sdks/rudderstack-php-sdk/