Open jamesozzie opened 2 years ago
following
Thank you and following!
please implement this. This feature would be very helpful both for bloggers and SEOs.
This would be a VERY useful thing for WordPress.
That's exactly on point! I hope Google implements it soon, it would make our lives so much easier ;)
+1
An option/setting/filter to save these values as post_meta would be equally as important as showing those values in the admin.
I'd love to see this implemented as well. Keenly following!
+1 Please!
+1 This would be incredibly helpful.
This would be really nice
@aaemnnosttv @marrrmarrr Have added some preliminary ACs. It makes sense to only implement this for GA4. Just need to add a bit more clarity on the "position" of this column.
I have also split this issue and created #6503 to implement the same column for the Pages list view separately.
The above will require Site Kit's assets to be loaded on the Posts wp-admin page similar to how we load them for the WP Dashboard.
In this case, wouldn't it make more sense to load the data in PHP and then serve it directly in the UI? I suppose that means a request on every page load since we don't cache data in PHP, but it seems very excessive to load an entire React app for every table row and then make a getReport
call for each.
I know this is venturing into implementation, but I wonder why this needs to be part of the ACs here, as it's more a "how" than a "what" for this issue. π€
@tofumatt I completely agree - we can discuss this at the IB level and happy to remove this point from the ACs.
Cool, in that case ACs here are good; moving to IB ππ»
@jimmymadon althought I think I'm not able to write the IB, as I'm not sure about how the PHP classes should be structured, some thoughts from my side:
I don't think the sorting functionality should be included in this issue. It's one thing load the data for the shown posts on every pageload, but its something completely different to add this sorting.
The sorting is done by the database query. The post lists are paginated to 10 posts / page (can be increased to 100 posts/page), so client side sorting won't work. To implement sorting, we would need to have the post views already in the database. Therefore we would need to somehow continuously sync the page view data from Analytics to our database and save the page views as a postmeta.
We currently don't store/sync analytics data to the WordPress database. If we want to have this sorting function, we should think in depth about how such a sync could look like and create a separate issue for it.
Just for the sake of completeness: instead of keeping the postview data in the WordPress database and synchronising it continuously, we could solve the pageview sorting "on the fly" with the help of "ORDER BY CASE". But that would still mean that we would have to load the pageviews of all posts. For WordPress installations with a large number of posts, this would mean quite a performance loss. Also, this would probably lead to compatibility problems with other plugins as we would have to edit the sql query directly instead of going via WP_Query. So this approach does not make sense.
@aaemnnosttv @tofumatt Any thoughts on how to implement sorting here based on what @derweili has raised?
Oh, actually, that's a great point and sometimes I didn't fully consider π
The filed issue says:
This could be a sortable column, as some of the other columns are within the same list views.
But really only "Title" and "Date" are sortable. Sorting by page views might be useful but adds a lot of complexity and overhead for minimal value, especially as you can view top-performing pages elsewhere in Analytics views.
It's not the primary purpose of this screen to view pages by page views, so I've updated the ACs and omitted the sortable requirement from it.
Can one make an input? I think it should display the pageviews (all time or if there is a way change it between days like the sitekit page) then the sorting should be HIGHEST and LOWEST.
Currently our theme has this, views shows all time pageviews to that particular URL.
@nfmohit As @derweili pointed out above, sorting will be hard here unless you figure out something completely different. If it is too cumbersome like we predict, I can remove sorting by page views from the AC and we can continue without it for now.
Apologies, @tofumatt already made that change! π
Putting in a vote for some API to (optionally?) use CRUD functions via PHP to get/set view counts in post_meta and/or options so we can use WP_Query to get the most popular or currently trending posts according to GA.
Hi @nfmohit, thanks for drafting this IB. I have a minor point, and a more substantial aspect that we need to consider.
The minor point is that we need to ensure the column is placed in the right order as per the AC, and can refer to this comment on the linked blog post for an example on how this can be achieved.
More substantially though, while the IB as is stands would work in terms of functionality, I see a problem with the approach.
By following this approach we'd end up with a synchronous series of GA4 report requests being made on the backend before the page is even rendered. This could be any number of requests - the default number of posts per page is 20.
This could introduce an unacceptably high delay to the page loading, which I am sure our users would not appreciate.
We need to batch the Analytics metric retrieval so that only one GA4 report request is made. However, having spent some time looking into it, I don't see this being realistically achievable on the PHP side, due to the way the code is structured for the post list page (for reference, here's the entry point to the loop where the table rows are rendered). Plus - even if we were to find a way, just adding one GA4 report request can introduce a significant delay, with a variety of factors in play.
I think that a better approach here would be to add the column with a placeholder for the data in PHP, and then use JS to make the GA4 report request and populate the data on the client-side. I'm not sure exactly how we'd do this without looking into it, but I'm sure it's achievable. What do you think?
Hi
Nice work guys, but how is this coming up? its been over a year now.
Nice work guys, but how is this coming up? its been over a year now.
Hi, @iamkingsleyf. Thank you for checking in. Unfortunately, this had to fall back a little since we had some other priorities that came up. We acknowledge this feature has received quite a good number of +1s, and we will work on putting this back in the pipeline again.
Nice work guys, but how is this coming up? its been over a year now.
Hi, @iamkingsleyf. Thank you for checking in. Unfortunately, this had to fall back a little since we had some other priorities that came up. We acknowledge this feature has received quite a good number of +1s, and we will work on putting this back in the pipeline again.
Alright thanks.
Hi @nfmohit, thanks for drafting this IB. I have a minor point, and a more substantial aspect that we need to consider.
Thank you for the kind IB review, @techanvil! Unfortunately, I had to leave this one hanging and unassigned myself as I had to adhere to other priorities. Apologies for not leaving a comment earlier, I remember to have left one but don't see it now, so it might have not gone through.
Since the approach needs some more thought, I'll unassign myself from here so that someone who has the capacity can pick up the IB review feedback. Thank you!
CC: @bethanylang
Thanks, @zutigrm. This is a good start, but we need to make some improvements to IB:
- Create new class, e.g.
Post_List_View_Analytics_Column
that will handle the report data and analytics column modification
Where should it be created? Which namespace should it use? I believe it should live in the Google\Site_Kit\Modules\Analytics_4
namespace, right?
- The class constructor will accept a
$modules
instance. This will be injected to provide access to the analytics module using itβsget_module( $module_slug )
method- Then using module instance check if analytics 4 module is available, e.q
$this->modules->get_module(Analytics_4::MODULE_SLUG)
, and if not, return early- ... and use it as param in
$this->modules->get_module(Analytics_4::MODULE_SLUG)->generate_posts_report()
method to get report data- In
includes/Plugin.php
on init hook, instantiatePost_List_View_Analytics_Column
and pass$modules
instance
- Call
register
method
This is not how it should work. The new class is part of the Analytics_4 functionality. Thus it should be instantiated and registered in the Analytics_4
class. In this case, we don't need to check whether the Analytics 4 module is available. The only thing that we will need to check is that the module is connected.
Also this will let us pass anything that we need from the module class to the column class. For example, we will need to pass the reference to the transients class to be able to read and manage transients. Use the Custom_Dimensions_Data_Available
class as an example.
@eugene-manuilov Thanks for the feedback. Originally I though it might be more handy to make this class more decoupled for flexibility as it would have access to the $modules
which would be easier to extend in the future for some other module, hence the proposal to instantiate it that way. But on the second thought, it does make more sense to group it with Analytics
module for instantiation as you suggested, as this will only rely on analytics data.
Updated IB per suggestions. I also included reseting of transient upon property change (something I missed originally), and showing N/A
as a value if there is no report data, and check for gathering data state.
@eugene-manuilov Reminder on this one please. :)
@bethanylang this one i want to discuss on our round table call that is scheduled for the next week. Planned to discuss it in Dec on the same call but we skipped those calls.
@ivonac4 i see you have just added this ticket to the Sprint 120, but I don't think we are going to work on it in this sprint. I still wait for our engineering sync call to discuss whether it makes sense to work on this ticket or we should better close it. So, probably better to remove it from the current sprint.
i would like to see this feature too, very helful one
@eugene-manuilov , @bethanylang latest comment by Eugene is that we are still considering if this ticket should be worked on. Who will decide on that? Should I move it back to Backlog then?
@ivonac4 Unfortunately we haven't had the roundtable meeting that @eugene-manuilov mentioned wanting to discuss this in in several months because of other priorities.
@eugene-manuilov Maybe you can discuss this with @aaemnnosttv in your next 1:1 sync? If we're not able to discuss it soon, we should probably move it to Backlog to avoid confusion about when/if it can be added to sprints. Thanks!
@aaemnnosttv I moved this back to Backlog as we haven't discussed it for 26 days now and latest comment by Eugene is that you need to check if it still makes sense to work on this ticket.
@ivonac4 There is an active thread on this issue in Slack right now, so it looks like this may be actually moving sooner than later.
@eugene-manuilov In the future, can you please make sure to leave updates on these issues if there is a discussion in Slack or elsewhere? That way we can avoid crossed wires like this. Thank you! cc @eclarke1
Perfect idea! Also, I need to use an eye icon near my post. It will be good if I can use it in the block to place in any area of my blog. Thank you.
Feature Description
Considering adding a total Google Analytics view count on both the pages and posts tab, as per the screenshot below, once Site Kit is set up with Analytics connected. This could be a sortable column, as some of the other columns are within the same list views.
This is a feature request on behalf of one user in the support forums.
Do not alter or remove anything below. The following sections will be managed by moderators only.
Acceptance criteria
screenPageViews
and dimension should bepagePathPlusQueryString
for the Post's URL. (Use existing GA4 datastore infrastructure to fetch this data).Implementation Brief
For overview and clarity
The approach will use transient data to store post IDs, which maps to associative array holding itβs permalinks and views. ID will be used to match the data. Transient should be stored for 24 hours to minimize calls to generate the report only when necessary - otherwise it will be updated earlier in case when new post is added, or usage of pagination/filter. Visible posts
permalinks
on admin list view will be used withinListFilter
dimension filter to make 1 batch request to pull the data. Transient will be allways replaced with new data, so at most it will hold 100 posts if user set 100 rows per table in the view which in most cases will be default 20. This data will be matched with$post_id
in new post column to display views.New class to handle transient data and post columns
includes/Modules/Analytics_4/Post_List_View_Analytics_Column
that will handle the report data and analytics column modification$transients
instance.is_data_available
andset_data_available
methods ofCustom_Dimensions_Data_Available
class. You can name themget_page_views_column_data
andset_page_views_column_data
for example, and include method for deleting the transientdelete_page_views_column_data
. And transient can be namedga4_page_views
.Manage columns
manage_columns
manage_posts_columns
, this hook passes$columns
param. Define new variablenew_columns
as an empty array, which should hold the columns.$columns
to find thecomments
key. Once found, add a new column, represented by the keyga4_page_views
, to the array. Use translatable stringGA Page Views
as value.comments
key is not found, check fordate
to pushga4_page_views
before it$new_columns[$column_key] = $column_value;
.comments
anddate
columns were found, addga4_page_views
at the end as last to ensure column is presentmanage_posts_custom_column
which will populate the data, it accepts 2 params$column_name
and,$post_id
$column_name
is notga4_page_views
to return earlyget_page_views_column_data
method and using$post_id
extract the current post data (as post IDs are the keys of stored data arrays)$post_id
exists in stored data array, output theviews
valuegathering data state
, returnN/A
Analytics_4 class
$post_list_view_analytics_column
protected variable, that will hold the instance ofPost_List_View_Analytics_Column
__construct
method set$post_list_view_analytics_column
, by assigning it a new instance ofPost_List_View_Analytics_Column
, you can follow this exampleprotected
method, saygenerate_posts_report
, which should accept$paths
array param (which will hold flat list of posts permalinks)null
for example to exit earlyreportOptions
in php array, like this one. WithdimensionFilter
forpagePathPlusQueryString
, and keep sameinListFilter
, forvalue
it will accept passed$paths
arrays consisting of posts links.Register method updates
$post_list_view_analytics_column
pre_get_posts
and utilize the$query
parameter passed to it! is_admin()
, to return early$query->is_main_query
andget_current_screen()->base !== 'edit-post'
to return early$this->is_connected()
, and if not, return earlyAll Posts
page in the main query, with analytics 4 module being connected and it can be proceedposts_selection
(when query will be setup), and pass the received$query
param from previous hook$current_posts_data
with empty array as value.$query->posts
to get the posts permalinks withget_permalink
function. Add these to the$current_posts_data
array, using the post ID as the key. Each post ID will map to an associative array with two keys:path
, holding the permalink, andviews
, initially set to0
to represent page views.$current_posts_data
is empty to return earlygathering data state
, to return early, using$this->is_data_available()
get_page_views_column_data
method of$post_list_view_analytics_column
and assign it to the variable, say$stored_data
$make_new_request
variable with valuefalse
, which will be used to determine if analytics request should be made or not$stored_data
,$make_new_request
should be true.$current_posts_data
keys, with$stored_data
keys (as permalinks can change), and in case of mismatch, set$make_new_request
to true$make_new_request
istrue
path
from$current_posts_data
and use it as param ingenerate_posts_report
method to get report dataviews
value in$current_posts_data
from report response to hold the metric value (screenPageViews
) for all posts, by matching theirpath
with received dimensionpagePathPlusQueryString
valueset_page_views_column_data
method of$post_list_view_analytics_column
N/A
to the page viewspropertyID
changes, transient should be emptied, follow the example from this filterdelete_page_views_column_data
method of$post_list_view_analytics_column
Test Coverage
Analytics_4->generate_posts_report
methodPost_List_View_Analytics_Column
classQA Brief
Changelog entry