Tutorials··7 min read

How to Log In As a Customer in WooCommerce (Safely)

A customer emails: "My cart shows the wrong price." You log in as them. You see exactly what they see. You fix it.

Easy to describe. Easy to do unsafely. In B2B stores this is a daily operation — reps place orders for customers, support reproduces bugs, admins test role-specific pricing. If you don't have a proper mechanism for it, people end up asking customers for their passwords. That's how data breaches start.

This guide covers: why you need a dedicated tool, what "safely" means, the naive implementation (and why it's risky), and the safe patterns.


Why you need this

Three common scenarios:

  1. Debugging a customer-reported issue — the customer says "my cart shows $100 but I was quoted $80." You need to see their cart exactly as they see it.
  2. Placing an order on behalf of the customer — phone orders, assisted checkout. See the place order on behalf guide for that workflow.
  3. Testing role-based configurations — you set up a new pricing rule for wholesale_tier_2. Before announcing it, you log in as a wholesale_tier_2 test user (or a real one) to verify.

Without a login-as-customer tool, your alternatives are:

  • Ask the customer for their password (terrible — don't)
  • Reset their password, log in as them, then reset again (worse — they're locked out, their session is killed, and you've probably broken a few things)
  • Create a test user mirroring their config (fine for testing, useless for reproducing real customer bugs)
  • Read their session data from the database (brittle; doesn't let you interact)

Login-as-customer solves this.


What "safely" means

A safe implementation has six properties:

  1. Only admins (or specific capabilities) can initiate — not every logged-in user
  2. Leaves a clear trail — who impersonated whom, when, for how long
  3. Makes impersonation obvious — a bar or banner the admin can't miss
  4. Is easily reversible — one click to switch back
  5. Doesn't expose the customer's login credentials — no password disclosure
  6. Distinguishes real customer actions from admin actions — so orders placed during impersonation are tagged

If a tool misses any of these, it's not production-ready.


The naive implementation

Here's the shortest possible "login as customer" — don't ship this:

// Don't do this
add_action( 'init', function () {
    if ( isset( $_GET['impersonate'] ) && current_user_can( 'manage_options' ) ) {
        $user_id = (int) $_GET['impersonate'];
        wp_set_current_user( $user_id );
        wp_set_auth_cookie( $user_id );
        wp_safe_redirect( home_url() );
        exit;
    }
});

This works. Visit /?impersonate=42 as an admin and you're now user 42. What's wrong:

  • No CSRF protection. Any link with ?impersonate=X sent to an admin logs them in as X.
  • No audit. Nothing is logged anywhere.
  • No indication of impersonation. You look like the customer to the customer if they're simultaneously logged in elsewhere (session conflicts).
  • No way back. Once you've swapped cookies, you're the customer. To get back to admin, you log out and log in again.
  • Replaces the admin's cookie. If you forget you're impersonating, you might do admin-level actions as the customer (which now fail because they don't have admin caps).

Every one of these is a real incident waiting to happen.


The safe pattern

Here's how it should work:

1. Nonce + capability check

add_action( 'admin_init', function () {
    if ( ! isset( $_GET['action'] ) || $_GET['action'] !== 'impersonate_user' ) return;
    check_admin_referer( 'impersonate_user_' . (int) $_GET['user_id'] );
    if ( ! current_user_can( 'edit_users' ) ) wp_die( 'Nope.' );
    // ...
});

2. Store the admin's identity separately

Don't replace the admin's login. Remember it. Example: store the admin's user ID in a dedicated cookie with a separate key.

$admin_id = get_current_user_id();
$target_id = (int) $_GET['user_id'];

setcookie(
    'wc_impersonator_id',
    wp_hash( $admin_id ) . '|' . $admin_id,
    [ 'expires' => time() + 3600, 'secure' => true, 'httponly' => true, 'samesite' => 'Strict' ]
);

wp_set_auth_cookie( $target_id );
wp_set_current_user( $target_id );

On revert, read the cookie, verify the hash, and restore the admin's auth cookie.

3. Log the session

Every impersonation should write a record to a dedicated log table or post type. Minimum fields:

  • Impersonator (admin user ID)
  • Impersonated (target user ID)
  • Started at
  • Ended at (fill on revert)
  • IP address
  • User agent

If a customer later says "why was my account accessed on March 12?", you produce this log.

4. Visible bar during impersonation

A sticky top bar rendered on every page when the impersonator cookie is present:

You are impersonating John Doe ([email protected]). [Switch back]

Without this, the admin forgets they're impersonating 30 minutes in, places an order accidentally, and you have a mess.

5. Tag actions performed during impersonation

Any order placed during impersonation should have order meta indicating:

  • _placed_by_admin: the impersonator's user ID
  • _placed_as_customer: yes

So when an auditor or customer asks "did I place this order myself?", your answer is supported by data.

6. Time-limited session

Impersonation shouldn't last forever. Expire after an hour or two. Forces the admin to consciously re-initiate if they need longer — which is rarely the case.


What about password-reset impersonation?

Some teams handle "login as customer" by:

  1. Resetting the customer's password
  2. Logging in as them
  3. Resetting the password again

This is a terrible pattern:

  • The customer is locked out of their account during the window
  • If they were logged in somewhere, they're kicked
  • Password change emails fire twice, confusing them
  • Your audit log shows "password changed" twice, not "admin X impersonated customer Y" — the trail is wrong
  • If anything interrupts step 3 (server error, admin leaves tab open), the customer's password is now whatever you set it to

Don't do this. Use a proper impersonation mechanism.


What we built

Shop As Customer is our plugin that implements all of the above:

  • Admin-only: requires edit_users capability by default; configurable
  • Dedicated impersonator cookie: the admin's session is preserved separately
  • Session log: dedicated admin screen with full history (impersonator, customer, duration, IP)
  • Persistent bar: sticky top banner you can't miss during impersonation
  • One-click revert: button in the bar returns you to your admin session
  • Auto-tagged orders: any order placed while impersonating is tagged with the admin's identity
  • Time-limited: configurable session duration with auto-expire

We built it because the alternatives we tried (user-switching.com's User Switching, various Woo-specific plugins) didn't have the audit trail, the sticky bar, or the Cart & Checkout Blocks compatibility we needed for B2B stores.


When you don't need a plugin

If you're a solo developer debugging your own personal WooCommerce install, the free User Switching plugin is probably enough. It has the switch-back mechanism and is widely trusted. It doesn't have the audit log, the sticky bar, or the "impersonation-tagged orders" pattern — but for a one-person shop, that might be overkill.

For anything shared — agency-managed stores, multi-admin teams, B2B stores with reps — you want the audit pieces.


Common mistakes

Using User Switching in a shared-admin environment without extending it. User Switching logs nothing. If two admins can impersonate, you'll have no record of who did what when a problem surfaces.

Allowing impersonation from outside WP admin. If there's a public URL that can trigger impersonation (/impersonate?user=X), it becomes a CSRF target. Keep the action inside WP admin with proper nonces.

Forgetting about simultaneous sessions. If the real customer is logged in and you impersonate them, WooCommerce session behavior can get weird — carts overwritten, recently-viewed products leaked, etc. A good tool handles this cleanly; ad-hoc solutions often don't.

Not logging the IP. "An admin logged in as the customer" is useful. "Admin Y logged in as the customer from IP 203.0.113.42 on 2026-03-12 at 14:08 UTC" is the answer to a real question.


The short version

  • You need a login-as-customer mechanism for any B2B store
  • Don't ask for customer passwords; don't reset them
  • The safe pattern requires: capability check, nonce, separate admin session, visible bar, action tagging, audit log
  • User Switching is fine for solo devs; for teams use a purpose-built plugin