-
Notifications
You must be signed in to change notification settings - Fork 56
feat(content-gate): add countdown block #4176
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
c4c29f2 to
d4b8352
Compare
0ce4d23 to
61ec477
Compare
28ca464 to
c28dd18
Compare
| $regex = "$category\/$name"; | ||
| } | ||
| $content = preg_replace( "/<!-- wp:$regex {?.*?}? -->.*?<!-- \/wp:$regex -->/s", '', $content ); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we don't filter this, any inner paragraph blocks within the content gate block will appear in the excerpt despite us explicitly returning an empty string in the render callback.
| 'newspack-blocks/checkout-button', | ||
| { | ||
| text: __( 'Subscribe now', 'newspack-plugin' ), | ||
| align: 'center', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note, alignment is broken in the editor right now and will be fixed in Automattic/newspack-blocks#2207
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR introduces a new content gate countdown block that displays remaining free metered views for a post or page. The block allows readers to see how many free articles they have left before hitting their metering limit.
- Adds a new WordPress block called "Content Gate Countdown" for the Newspack plugin
- Implements frontend JavaScript functionality to dynamically update countdown for anonymous users
- Integrates with existing metering system to display current usage against total allowed views
Reviewed Changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| webpack.config.js | Adds build entry for the new countdown block's frontend view script |
| src/blocks/index.js | Registers the new countdown block with conditional loading based on membership availability |
| src/blocks/content-gate-countdown/view.js | Frontend JavaScript that updates countdown display for anonymous users |
| src/blocks/content-gate-countdown/style.scss | CSS styling for the countdown block's responsive layout |
| src/blocks/content-gate-countdown/index.js | Block registration with metadata, settings, and save function |
| src/blocks/content-gate-countdown/edit.jsx | Block editor component with inspector controls and preview functionality |
| src/blocks/content-gate-countdown/class-content-gate-countdown-block.php | PHP class handling block registration, rendering, and server-side logic |
| src/blocks/content-gate-countdown/block.json | Block metadata defining attributes and supported features |
| packages/icons/src/content-gate-countdown.js | SVG icon component for the countdown block |
| packages/icons/index.js | Exports the new countdown icon |
| includes/plugins/wc-memberships/class-metering.php | Adds utility methods for retrieving metering data |
| includes/plugins/wc-memberships/class-memberships.php | Excludes countdown block from post excerpts |
| includes/class-blocks.php | Includes countdown block class and provides metering data to editor |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
src/blocks/content-gate-countdown/class-content-gate-countdown-block.php
Show resolved
Hide resolved
miguelpeixe
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's working mostly well! I encountered a few issues and suggestions that I commented inline.
| <Placeholder | ||
| icon={ caution } | ||
| label={ __( | ||
| 'The content gate countdown block will only display in restricted content when metering is enabled.', | ||
| 'newspack-plugin' | ||
| ) } | ||
| className="no-metering" | ||
| /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should also have blockProps, otherwise the element won't interact well with the editor.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added in c9ed5ab
| use Newspack; | ||
| use Newspack\Memberships; | ||
| use Newspack\Memberships\Metering; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we namespace this to Newspack instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good call. Changed in c9ed5ab
| use Newspack\Memberships; | ||
| use Newspack\Memberships\Metering; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is superfluous as we're already in the Newspack namespace.
We can keep Newspack\Memberships\Metering, but I don't think it's bad to use Memberships\Metering in the code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It feels cleaner to use just Metering in the code imo, so I'll keep it as is. Happy to change it if you feel strongly about it though!
| if ( ! Metering::is_metering() ) { | ||
| return ''; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we also need to bail on ! Memberships::is_post_restricted(), otherwise the block will render for readers with access.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah. Good catch! I had removed this part of the check while working on styles and forgot to re-add it before submitting for review. Fixed in c9ed5ab
| $countdown = sprintf( | ||
| /* translators: 1: remaining metered views, 2: total metered views. */ | ||
| __( '%1$d/%2$d', 'newspack-plugin' ), | ||
| max( 0, $total_views - $remaining_views ), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The amount was already calculated here. It's going full circle and returning the number of articles read 😄
Speaking of which, even though I'm aware that the block is called countdown, reading 4/5 on my first visit was a bit odd. Not sure if it's because of the way it's phrased, maybe it's just me. @thomasguillot can you confirm whether it should be the number of articles read or remaining?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The amount was already calculated here. It's going full circle and returning the number of articles read 😄
Ha. Yeah. I initially had this counting down using the remaining count. Then at the last second I thought it made more sense to show the number of articles read and made this change. I've gone back to remaining count here in c9ed5ab, but I'd like to get confirmation from @thomasguillot as well to know what this number should be.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's meant to be 4 articles read out of 5. So the first visit should be 1/5
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So you have read 1 article. And you have 5 free.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And not read 4 articles
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @thomasguillot! Updated this to count up in 68df86c
| "default": "" | ||
| } | ||
| }, | ||
| "supports": { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking at the design, it seems that the block should also support align, so it can also render wide and full width.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch! Added in c9ed5ab
| }, | ||
| ], | ||
| [ | ||
| 'newspack-blocks/checkout-button', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
WDYT of adding "backgroundColor":"primary" to the template as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure thing! This requires setting textColor to secondary to avoid contrast issues. Added in c9ed5ab
| // Admin is always logged in, so if no loggedin metered views are set, use the anonymous views instead. | ||
| const totalViews = loggedinViews > 0 ? loggedinViews : anonymousViews; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a bit confusing. Isn't this about whether the post gate has metering configured?
Something like:
| // Admin is always logged in, so if no loggedin metered views are set, use the anonymous views instead. | |
| const totalViews = loggedinViews > 0 ? loggedinViews : anonymousViews; | |
| const hasMetering = loggedinViews || anonymousViews; |
Still, this does not take into account whether metering is active (the metering meta)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem this is solving is in the editor, the user (admin) is always logged in, so if the post is metered for anonymous readers and not registered readers, then the views will always be 0 in the editor.
I named this variable totalViews because below we use it when displaying the countdown: https://github.com/Automattic/newspack-plugin/pull/4176/files/d116d5625454735dbf6c024e91b43626c93b6705#diff-da1ae48178cfb1fb24cf269739fc3d32517200fb0105cefdba1155dba8c45f9eR98
As for using the || operator instead of the ternary, I thought the ternary made it a bit clearer that we are falling back to anonymous views if loggedin views was 0. But both will have the same result, so happy to change it if you prefer!
Still, this does not take into account whether metering is active (the metering meta)
Yeah. I decided not to check the meta here because having both loggedinViews and anonymousViews be 0 is effectively the same as not having metering active.
c9ed5ab to
009cbde
Compare
miguelpeixe
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the revisions! It's working great, but I found a couple of issues:
| // Replace countdown for anonymous users. | ||
| const countdown = sprintf( | ||
| /* translators: 1: current number of metered views, 2: total metered views. */ __( '%1$d/%2$d', 'newspack-plugin' ), | ||
| content.length, | ||
| count | ||
| ); | ||
| countdownEl.textContent = countdown; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When accessing an article for the first time with anonymous metering, I'm getting 0 reads:
We may need to listen to the metering_restricted activity dispatch for an accurate number here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Strange, on my end the metering script is always run before the countdown script, and the value is correctly updated:

I checked in multiple browsers to confirm this isn't some browser loading order quirk. In any case, I added the metering script handle as a dependency when enqueuing the countdown script to ensure this is always the case in 4202b80
| } | ||
| wp_enqueue_style( | ||
| 'newspack-content-gate-countdown-block', | ||
| \Newspack\Newspack::plugin_url() . '/dist/content-gate-countdown-block.css', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure why, but I'm getting 404 for this asset.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like the styles for this are being bundled into commons by webpack. Not sure if this is what you are seeing. On my end, there is no content-gate-countdown-block.css being fetched. Instead the styles live in commons.css
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah sorry! Seeing it now. I guess we don't need to enqueue the styles here 🤷♂️
|
Hey @chickenn00dle, good job getting this PR merged! 🎉 Now, the Please check if this PR needs to be included in the "Upcoming Changes" and "Release Notes" doc. If it doesn't, simply remove the label. If it does, please add an entry to our shared document, with screenshots and testing instructions if applicable, then remove the label. Thank you! ❤️ |
# [6.20.0-alpha.1](v6.19.0...v6.20.0-alpha.1) (2025-09-25) ### Bug Fixes * Improve help text for Guest Contributor checkbox ([#4187](#4187)) ([5790f3d](5790f3d)) * newspack-plugin delay ([#4184](#4184)) ([22e8dc2](22e8dc2)) * update download URL for db.php ([#4193](#4193)) ([4d363db](4d363db)) ### Features * **collections:** add Collections block ([#4166](#4166)) ([1185157](1185157)) * **collections:** add logic for opening links in new tabs ([#4174](#4174)) ([07a5545](07a5545)) * **collections:** collections block feedback ([#4185](#4185)) ([0d0210c](0d0210c)) * **collections:** remove feature flag ([#4195](#4195)) ([b1619ef](b1619ef)) * **collections:** replace archive grid with collections block ([#4178](#4178)) ([d0cbadd](d0cbadd)) * **content-gate:** add countdown block ([#4176](#4176)) ([f8fe757](f8fe757)) * **my-account:** subscription switch modal ([#4177](#4177)) ([28c26e7](28c26e7)) * subscription tier modal ([#4164](#4164)) ([4d6ebe2](4d6ebe2))
|
🎉 This PR is included in version 6.20.0-alpha.1 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
This reverts commit f8fe757.
# [6.20.0](v6.19.0...v6.20.0) (2025-10-06) ### Bug Fixes * ga4 events for gate interactions and tiered modal ([#4209](#4209)) ([2d35768](2d35768)) * Improve help text for Guest Contributor checkbox ([#4187](#4187)) ([5790f3d](5790f3d)) * newspack-plugin delay ([#4184](#4184)) ([22e8dc2](22e8dc2)) * remove content gate countdown block ([0204e58](0204e58)) * update download URL for db.php ([#4193](#4193)) ([4d363db](4d363db)) ### Features * **collections:** add archive link in settings page ([#4203](#4203)) ([42694ec](42694ec)) * **collections:** add Collections block ([#4166](#4166)) ([1185157](1185157)) * **collections:** add css classes to meta elements ([#4208](#4208)) ([7fbf7e9](7fbf7e9)) * **collections:** add logic for opening links in new tabs ([#4174](#4174)) ([07a5545](07a5545)) * **collections:** collections block feedback ([#4185](#4185)) ([0d0210c](0d0210c)) * **collections:** remove feature flag ([#4195](#4195)) ([b1619ef](b1619ef)) * **collections:** replace archive grid with collections block ([#4178](#4178)) ([d0cbadd](d0cbadd)) * **content-gate:** add countdown block ([#4176](#4176)) ([f8fe757](f8fe757)) * **my-account:** subscription switch modal ([#4177](#4177)) ([28c26e7](28c26e7)) * subscription tier modal ([#4164](#4164)) ([4d6ebe2](4d6ebe2))
|
🎉 This PR is included in version 6.20.0 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |

All Submissions:
Changes proposed in this Pull Request:
Closes https://linear.app/a8c/issue/NPPM-2204/content-restriction-block-shows-countdown-before-you-hit-the-wall-you
This PR adds a new content gate countdown block that displays the remaining free metered views for a post or page:
How to test the changes in this Pull Request:
Other information: