WooCommerce Function of the Week: wc_get_endpoint_url

This week’s WooCommerce function is about endpoints. What’s an endpoint? Endpoints are “an extra part in the website URL that is detected to show different content when it’s present. For example: You may have a โ€˜My Accountโ€™ page shown at yoursite.com/my-account. When the endpoint โ€˜edit-accountโ€™ is appended to this URL, making it โ€˜yoursite.com/my-account/edit-accountโ€˜ then the Edit Account page is shown instead of the My Account page.” (Source: WooCommerce).

There are dozens of WooCommerce endpoints, especially for the Checkout and My Account page, as well as custom endpoints added by third-party WooCommerce plugins. It’s difficult to remember all the different URLs, so here comes wc_get_endpoint_url to the rescue.

As usual, in this article, we’ll study the WooCommerce core function code for wc_get_endpoint_url in this tutorial, see where and why it’s used, and finally, we’ll look at a brief case study. Enjoy!

Function code

The wc_get_endpoint_url function can be found under \woocommerce\includes\wc-page-functions.php:

 * Get endpoint URL.
 * Gets the URL for an endpoint, which varies depending on permalink settings.
 * @param  string $endpoint  Endpoint slug.
 * @param  string $value     Query param value.
 * @param  string $permalink Permalink.
 * @return string
function wc_get_endpoint_url( $endpoint, $value = '', $permalink = '' ) {
	if ( ! $permalink ) {
		$permalink = get_permalink();

	// Map endpoint to options.
	$query_vars = WC()->query->get_query_vars();
	$endpoint   = ! empty( $query_vars[ $endpoint ] ) ? $query_vars[ $endpoint ] : $endpoint;
	$value      = ( get_option( 'woocommerce_myaccount_edit_address_endpoint', 'edit-address' ) === $endpoint ) ? wc_edit_address_i18n( $value ) : $value;

	if ( get_option( 'permalink_structure' ) ) {
		if ( strstr( $permalink, '?' ) ) {
			$query_string = '?' . wp_parse_url( $permalink, PHP_URL_QUERY );
			$permalink    = current( explode( '?', $permalink ) );
		} else {
			$query_string = '';
		$url = trailingslashit( $permalink );

		if ( $value ) {
			$url .= trailingslashit( $endpoint ) . user_trailingslashit( $value );
		} else {
			$url .= user_trailingslashit( $endpoint );

		$url .= $query_string;
	} else {
		$url = add_query_arg( $endpoint, $value, $permalink );

	return apply_filters( 'woocommerce_get_endpoint_url', $url, $endpoint, $value, $permalink );

Now, it’s a bit complex to explain everything, so let’s start with the function arguments:

  • $endpoint: this is what you have under WordPress Dashboard > WooCommerce > Settings > Advanced > “Checkout endpoints” and “Account endpoints.” That’s the only thing you need to remember or look at when using the function.
  • $value: this is an optional URL parameter. For example, the checkout “Thank You” page endpoint has the order ID in the URL.
  • $permalink: this is simply the Checkout or My Account URL, based on the endpoint you need to get the URL for. By default, the permalink is the current page URL. (See the first part of the function.)

So that’s basically everything, as the rest of the function is related to the permalinks settings. It checks whether the permalink has a query parameter already, and finally, there’s a handy filter woocommerce_get_endpoint_url” in case you want to manipulate the output โ€” i.e., the URL.

I think it’s easier if we go through the usage and case study now so we can see woocommerce_get_endpoint_url in action.

Function usage

The woocommerce_get_endpoint_url function is actually used quite often inside WooCommerce core. By doing a quick file search we find there are many results (26 exactly, including the function), so I’ll paste a couple here:

 * Generates a URL so that a customer can pay for their (unpaid - pending) order. Pass 'true' for the checkout version which doesn't offer gateway choices.
 * @param  bool $on_checkout If on checkout.
 * @return string
public function get_checkout_payment_url( $on_checkout = false ) {
	$pay_url = wc_get_endpoint_url( 'order-pay', $this->get_id(), wc_get_checkout_url() );

	if ( $on_checkout ) {
		$pay_url = add_query_arg( 'key', $this->get_order_key(), $pay_url );
	} else {
		$pay_url = add_query_arg(
				'pay_for_order' => 'true',
				'key'           => $this->get_order_key(),

	return apply_filters( 'woocommerce_get_checkout_payment_url', $pay_url, $this );

In this get_checkout_payment_url function, wc_get_endpoint_url is used to get the “Order Pay” page. It comes up when there is a pending order and you manually invoice customers. Simple enough:

  1. Call wc_get_endpoint_url
  2. Define the $endpoint ('order-pay')
  3. Define the $value (order ID)
  4. Define the $permalink (wc_get_checkout_url), which is a shortcut to get the checkout URL without worrying about its custom page URL, which may vary. (E.g. if you rename it to /basket it will give you /basket.)

The function then adds a query parameter (the order key) and returns the complete Order Pay URL.

Another one:

 * Returns the url to the lost password endpoint url.
 * @param  string $default_url Default lost password URL.
 * @return string
function wc_lostpassword_url( $default_url = '' ) {
	// Avoid loading too early.
	if ( ! did_action( 'init' ) ) {
		return $default_url;

	// Don't redirect to the woocommerce endpoint on global network admin lost passwords.
	if ( is_multisite() && isset( $_GET['redirect_to'] ) && false !== strpos( wp_unslash( $_GET['redirect_to'] ), network_admin_url() ) ) { // WPCS: input var ok, sanitization ok, CSRF ok.
		return $default_url;

	$wc_account_page_url    = wc_get_page_permalink( 'myaccount' );
	$wc_account_page_exists = wc_get_page_id( 'myaccount' ) > 0;
	$lost_password_endpoint = get_option( 'woocommerce_myaccount_lost_password_endpoint' );

	if ( $wc_account_page_exists && ! empty( $lost_password_endpoint ) ) {
		return wc_get_endpoint_url( $lost_password_endpoint, '', $wc_account_page_url );
	} else {
		return $default_url;

In this case, wc_get_checkout_url is used to get the “Lost Password” endpoint URL, and it uses the $lost_password_endpoint from the WooCommerce settings, no $value, and the My Account page URL as $permalink.

Basically, it’s a shortcut to get URLs that you don’t want to copy and paste manually every time.

As I mentioned earlier, wc_get_checkout_url is very useful when you customize the Checkout or My Account page URL.

It’s much easier to get the “edit-address” My Account endpoint like this…

$url = /my-account/edit-address

…than it is to do something like this:

$url = wc_get_endpoint_url( 'edit-address', '', wc_get_page_permalink( 'myaccount' ) );

But what if the WordPress admin has changed the “my-account” page slug to something else, like “account?”

Well, this is why you can safely use wc_get_checkout_url. No matter what the base URL is, it will always give you the correct result.


$url = '/my-account/edit-address'; // SHOULD BE '/account/edit-address'


$url = wc_get_endpoint_url( 'edit-address', '', wc_get_page_permalink( 'myaccount' ) );

The wc_get_page_permalink( 'myaccount' ) part is the one that will get the correct base permalink no matter what the My Account page slug happens to be.

Have I confused you enough?

Let’s see a practical example.

WooCommerce case study

Let’s say I need to redirect customers to the “Downloads” section under My Account upon purchase. It could be I have an MP3 shop, and I want customers to access the Downloads tab immediately after their purchase.

Suppose the WordPress admin has renamed the My Account page slug to “/dashboard.” If I use a hardcoded URL, the redirect will return a 404 error because “/my-account” does not exist.

So, let’s see:

  1. How to make a redirect on the Thank You page โ€” see my WooCommerce: Redirect to Custom Thank you Page tutorial for reference.
  2. How to redirect to the correct My Account endpoint.
 * @snippet       Redirect to Downloads Upon WooCommerce Order Creation
 * @how-to        Get CustomizeWoo.com FREE
 * @author        Rodolfo Melogli
 * @compatible    WooCommerce 6
 * @donate $9     https://businessbloomer.com/bloomer-armada/

add_action( 'woocommerce_thankyou', 'bbloomer_redirect_to_downloads' );
function bbloomer_redirect_to_downloads( $order_id ){
    $order = wc_get_order( $order_id );
    if ( ! $order->has_status( 'failed' ) ) {
        wp_safe_redirect( wc_get_endpoint_url( 'downloads', '', wc_get_page_permalink( 'myaccount' ) ) );

Once woocommerce_thankyou fires (on the Thank You page), this function checks to ensure that the order has not failed, and if all is well, it redirects the customer to the Downloads endpoint, which will be:


… and not /my-account/downloads, which would have given us a 404.

And that is how to use wc_get_endpoint_url!

Rodolpho Melogli

Rodolfo Melogli is an author, WooCommerce expert, and WordCamp speaker, Rodolfo has worked as an independent WooCommerce freelancer since 2011. He teaches WooCommerce development at Business Bloomer.

Similar Posts