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) |
Page Loaded |
| 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/