# Make aligned 4-week subscriptions renew 4 weeks out

> A WooCommerce subscription billed every 4 weeks and aligned to Saturday renews on the very next Saturday after sign-up. Two tested ways to move that first renewal to the end of the first 4 weeks: a small filter, or a free trial plus a sign-up fee.

Published: 2026-10-15T12:00:00.000Z
Author: Shameem Reza
Category: Code Snippets
Canonical: https://shameemreza.com/aligned-4-week-subscriptions-first-renewal/

---

A teammate asked in our support Slack this week if anyone had a workaround for a store that sells a subscription every 4 weeks, aligned to Saturday. The renewals did land on Saturdays. The problem was the first one. It came a few days after sign-up, and the 4-week rhythm only started after that.

I set it up on my local site to see it myself. A $40 product, billed every 4 weeks, aligned to Saturday. I signed up on Thursday, October 15, and the first renewal was set for Saturday, October 17. Two days. If the store charges the full amount at sign-up, that's $40 on Thursday and another $40 on Saturday, before tax.

My teammate ended up writing their own snippet and sent it to the store owner. By then I'd tested two other routes, one with code and one without. Both are below.

**TLDR**

> WooCommerce Subscriptions sets the first renewal of an aligned subscription to the next aligned day, whatever the billing interval. For "every 4 weeks on Saturday", a Thursday sign-up renews two days later. A filter on `woocommerce_subscriptions_synced_first_payment_date` moves it three weeks later, to the last Saturday before the first 4 weeks are up. Without code, a 3-week free trial plus a sign-up fee equal to the price gets the same dates. Tested on Subscriptions 9.3.0.

## Why the first renewal comes so early

This one is documented. The Subscriptions guide on [creating an aligned subscription product](https://woocommerce.com/document/subscriptions/billing-date-alignment/creating-an-aligned-subscription-product/) says the plugin ignores longer billing intervals when it sets the first aligned date. It uses the next aligned day that comes up. The guide's own example is a quarterly subscription aligned to the 1st: sign up on April 6 and the first renewal is May 1, not July 1.

I still wanted to see where that happens before reaching for a fix. The date comes from `calculate_first_payment_date()` in `includes/core/class-wc-subscriptions-synchroniser.php`. At line 906, it treats the product's billing interval as 1 unless First billing behavior is set to Charge full amount at sign-up. So an every-4-weeks product gets aligned like a weekly one, and the code picks the next Saturday.

First billing behavior lives under WooCommerce > Settings > Subscriptions, in the Billing date alignment section (it was called Synchronization before Subscriptions 9.0). It has three choices: Charge full amount at sign-up, Charge on the next billing date, and Prorate until the next billing date. I checked the first renewal date Subscriptions calculates for a sign-up on each day from Monday, October 12, to Sunday, October 18, under each one.

![The Billing date alignment section in WooCommerce Subscriptions settings, with First billing behavior set to Prorate until the next billing date](https://shameemreza.com/_astro/aligned-4-week-subscriptions-first-renewal-settings.D1yzeGaE.png)

Prorate and Charge on the next billing date behave the way the guide says. Every sign-up from Monday to Saturday renewed on October 17, and a Sunday one renewed on October 24. For a Thursday sign-up, Prorate charged $2.86 before tax, which is 2 of 28 days of $40, and then the full $40 on Saturday. That's fair to the customer. It just isn't what the store owner wanted.

![Cart for the every-4-weeks-on-Saturday product on Thursday, October 15: $3.15 due today with tax, and the recurring total starting October 17, 2026](https://shameemreza.com/_astro/aligned-4-week-subscriptions-first-renewal-cart-default.BNdOTG2y.png)

Charge full amount at sign-up is the odd one. It's the setting that's supposed to count the full interval, and the code does pass the real interval through. But only the Sunday sign-up got it. That one renewed on November 14. The other six days still renewed on October 17, right after paying in full. That's one day out of seven, so I wouldn't rely on that setting here.

![Hand-drawn comparison of a Thursday sign-up on a $40 every-4-weeks-on-Saturday subscription: by default it renews two days later, with the snippet and with the trial plus sign-up fee it renews on Saturday, November 7](https://shameemreza.com/_astro/aligned-4-week-subscriptions-first-renewal-routes.DNiHk6GK.png)

Both routes below aim for the same date: the last Saturday before the first 4 weeks are up, then every 4 weeks after. For a Thursday sign-up, that's Saturday, November 7.

## Route one: the snippet

`calculate_first_payment_date()` runs its result through the `woocommerce_subscriptions_synced_first_payment_date` filter before returning it (line 1032). The filter gets the date, the product, the return format, and the date it calculated from. That last one already includes any free trial.

So the snippet lets Subscriptions find the next Saturday first. On an every-4-weeks product, if that Saturday is less than three weeks away, the snippet moves it three weeks later.

```php
// Purpose: Move the first renewal of aligned multi-week subscriptions (for example, every 4 weeks on Saturday) to the aligned day in the last week of the first billing period, instead of the very next aligned day.
// Tested with: WordPress 7.1.3, WooCommerce 11.2.1, WooCommerce Subscriptions 9.3.0.
// Note: Only affects weekly products with a billing interval above 1. Sign-ups on the aligned day itself are left as they are.
// Note: Use with the "Charge full amount at sign-up" or "Prorate until the next billing date" setting. With "Charge on the next billing date", customers get the extra weeks free.
// Note: Covers subscription products. Products sold through subscription plans are not covered.

add_filter(
	'woocommerce_subscriptions_synced_first_payment_date',
	function ( $first_payment, $product, $type, $from_date ) {
		if ( empty( $first_payment ) || ! is_a( $product, 'WC_Product' ) ) {
			return $first_payment;
		}

		if ( 'week' !== WC_Subscriptions_Product::get_period( $product ) ) {
			return $first_payment;
		}

		$extra_weeks = (int) WC_Subscriptions_Product::get_interval( $product ) - 1;

		if ( $extra_weeks < 1 ) {
			return $first_payment;
		}

		$first_timestamp = is_numeric( $first_payment ) ? (int) $first_payment : wcs_date_to_time( $first_payment );

		if ( WC_Subscriptions_Synchroniser::is_today( $first_timestamp ) ) {
			return $first_payment;
		}

		// $from_date already includes any free trial. Skip when the date is already a full interval out.
		$from_timestamp = $from_date ? wcs_date_to_time( $from_date ) : time();

		if ( $first_timestamp - $from_timestamp >= $extra_weeks * WEEK_IN_SECONDS ) {
			return $first_payment;
		}

		$first_timestamp = wcs_add_time( $extra_weeks, 'week', $first_timestamp );

		return 'mysql' === $type ? gmdate( 'Y-m-d H:i:s', $first_timestamp ) : $first_timestamp;
	},
	10,
	4
);
```

[View this snippet on Gist](https://gist.github.com/shameemreza/976e9bcfaf3950cd850c2cd9f85d12ce)

Add it to your child theme's `functions.php`, or use a plugin like [Code Snippets](https://wordpress.org/plugins/code-snippets/) or [WPCode](https://wordpress.org/plugins/wpcode/). It needs WooCommerce Subscriptions active.

A few choices in there are on purpose. The distance check is what keeps the Sunday case right under Charge full, since that sign-up already lands 27 days out and doesn't need three more weeks. The `is_today()` check leaves aligned-day sign-ups alone. And monthly or yearly products return early, because the filter only touches weekly periods with an interval above 1.

I checked it the same way, every day from October 12 to 18, under Charge full and Prorate. Monday to Saturday sign-ups renewed on November 7, and the Sunday one on November 14, 27 days out.

Then I put two test checkouts through on Thursday. Both subscriptions came out with the next payment on Saturday, November 7. Under Prorate, the sign-up charge was $36.15 with tax, which is 23 of 28 days of the price.

![The same cart with the snippet active: $36.15 due today with tax, and the recurring total starting November 7, 2026](https://shameemreza.com/_astro/aligned-4-week-subscriptions-first-renewal-cart-snippet.CAyAnTMM.png)

## Route two: a free trial plus a sign-up fee

This one needs no code, and it came from looking at the same function again. When a product has a free trial, `calculate_first_payment_date()` starts counting from the end of the trial, then aligns to the next Saturday. So a trial that's one week shorter than the interval lands the first renewal in the right week. The sign-up fee takes the place of the first payment.

On the product:

1. Set the price to $40 every 4 weeks.
2. Turn on Align billing and pick Saturday.
3. Add a free trial of 3 weeks.
4. Set the sign-up fee to $40, the same as the price.

Then set First billing behavior to Prorate until the next billing date or Charge on the next billing date.

I checked every day of the week again, and the dates match the snippet: November 7 for Monday to Saturday sign-ups, November 14 for Sunday. A Thursday test checkout charged $44, the $40 sign-up fee plus tax, and the next payment was Saturday, November 7.

![Product page for the trial setup: $44.00 every 4 weeks on Saturday, Free trial: 3 weeks, Sign-up fee: $44.00, and First payment: November 7, 2026](https://shameemreza.com/_astro/aligned-4-week-subscriptions-first-renewal-trial-product.DSj2azxX.png)

This route has two catches. The product page lists "Free trial: 3 weeks" and "Sign-up fee: $44.00" under the price, and the customer pays that $44 at checkout. Changing that wording takes code, which defeats the point of a no-code route.

The other catch is the setting. Under Charge full amount at sign-up, the Sunday sign-up renewed on December 5. That's seven weeks for one payment. Sunday is again the one day that gets the full interval, and here it comes on top of the trial. And First billing behavior is a store-wide setting, so it changes every aligned product in the store.

## Which one I'd pick

If the store charges the full amount at sign-up, route two means switching a store-wide setting, and that changes every aligned product. For a store like that, I'd use the snippet. It's also the better fit when the product page has to say exactly what the customer pays.

On Prorate or Charge on the next billing date, and if the store owner can live with the trial wording, I'd go with route two. It's settings only, so there's no code to keep working across updates.

A few things to know before using either one:

- I couldn't put a Saturday sign-up through a test checkout, because my site's date was a Thursday. The snippet skips that case on purpose and leaves it to Subscriptions.
- I haven't tested resubscribes or plan switches on the trial route.
- The snippet doesn't cover products sold through subscription plans (what used to be All Products for Subscriptions). Those take a different code path that skips this filter.
- With Charge on the next billing date, the snippet gives customers the extra three weeks free, since nothing is charged until the first renewal.

Whichever route you pick, put one test order through first and check the date next to the recurring total in the cart. That's where the two-day renewal shows up.
