feat(insights): conversion source-mix + time-to-convert distributions#373
Draft
dkoo wants to merge 10 commits into
Draft
feat(insights): conversion source-mix + time-to-convert distributions#373dkoo wants to merge 10 commits into
dkoo wants to merge 10 commits into
Conversation
…source-mix Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…on) for Tab 3 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Rewrite the three pre-existing source-mix tests that asserted the old Woo_Order_Resolver bucketing behaviour against the new Source_Matcher timestamp-proximity attribution path: - test_source_mix_subscribers_returns_populated_slices_on_success: injects Subscribers_Metric returning 3 records; BQ supplies a gate event and a prompt event timed within 1800 s of two records; the third is unmatched → direct. Asserts gate=1, prompt=1, direct=1, total=3, pct=1/3 each. - test_source_mix_subscribers_guards_zero_total: the zero-total with non-empty records is unreachable under Source_Matcher (every record gets exactly one source). Replaced with the equivalent guard: a single record with no matching event goes to direct; gate/prompt buckets have count=0 and must produce pct=0.0 (no division error via $safe guard). - test_source_mix_donors_returns_populated_slices_on_success: mirrors the subscribers test using Donors_Metric and the donors query name. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… probe gate Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ility gate Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…pendent Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR wires several Insights → Conversion Journey (Tab 3) metrics to live data by using WooCommerce as the identity spine and attaching BigQuery-derived “source” (gate/prompt/direct) via timestamp-window matching, plus adds a UI caption clarifying which charts ignore the selected date range.
Changes:
- Update
Conversion_Metricto compute subscriber/donor source-mix from Woo conversion records, attributing source via timestamp proximity to BigQuery events. - Add new storage + metric-layer methods for “windowed conversion records” and “all-history conversion lags” needed by the new distributions.
- Add UI captioning for snapshot (all-history) charts and expand PHP/JS test coverage for the new behavior.
Reviewed changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| plugins/newspack-plugin/includes/wizards/insights/metrics/class-conversion-metric.php | Implements live source-mix attribution via Woo records + timestamp-matched BigQuery events; adds time-to-convert distributions and subscriber→donor lag CDF logic. |
| plugins/newspack-plugin/includes/wizards/insights/storage/class-storage-interface.php | Extends subscribers storage contract with windowed subscriber records + all-history subscription lag rows. |
| plugins/newspack-plugin/includes/wizards/insights/storage/class-donors-storage-interface.php | Extends donors storage contract with windowed donor records, donation lag rows, and subscriber→donor lag rows. |
| plugins/newspack-plugin/includes/wizards/insights/storage/class-hpos-storage.php | Implements new subscriber record + subscription lag queries for HPOS backend. |
| plugins/newspack-plugin/includes/wizards/insights/storage/class-legacy-storage.php | Implements new subscriber record + subscription lag queries for legacy CPT backend. |
| plugins/newspack-plugin/includes/wizards/insights/storage/class-hpos-donors-storage.php | Implements new donor record, donation lag, and subscriber→donor lag queries for HPOS backend. |
| plugins/newspack-plugin/includes/wizards/insights/storage/class-legacy-donors-storage.php | Implements new donor record, donation lag, and subscriber→donor lag queries for legacy CPT backend. |
| plugins/newspack-plugin/includes/wizards/insights/metrics/class-subscribers-metric.php | Exposes new storage methods (windowed subscriber records + subscription conversion lags) at the metric layer. |
| plugins/newspack-plugin/includes/wizards/insights/metrics/class-donors-metric.php | Exposes new storage methods (windowed donor records + donation lags + subscriber→donor lags) at the metric layer. |
| plugins/newspack-plugin/includes/wizards/insights/fixtures/conversion-fixture.php | Updates fixture shape to reflect that 4.4 is now implemented (“populated” but hidden in the fixture). |
| plugins/newspack-plugin/tests/unit-tests/insights/class-test-conversion-metric.php | Updates/expands unit tests for new source-mix attribution + new time-to-convert / lag distributions. |
| plugins/newspack-plugin/tests/unit-tests/insights/class-test-conversion-journey-storage.php | Adds delegation/contract tests for the new storage/metric methods. |
| plugins/newspack-plugin/src/wizards/insights/tabs/conversion/HowLongConversionsTakeSection.tsx | Adds optional captions to the 4.2/4.3/4.4 “snapshot” charts indicating they ignore date range. |
| plugins/newspack-plugin/src/wizards/insights/tabs/conversion/HowLongConversionsTakeSection.test.tsx | Adds a test asserting the snapshot caption appears on exactly the intended charts. |
Comment on lines
+883
to
+887
| private function compute_source_mix( string $query_name, array $records, DateTimeInterface $start, DateTimeInterface $end ): array { | ||
| $bq = $this->proxy->query( $query_name, $start, $end ); | ||
| // Precedence intentional: a genuine proxy error must surface as the 'error' envelope, not be masked as 'empty'. | ||
| if ( is_wp_error( $bq ) ) { | ||
| return $this->error_collection( 'slices', $bq ); |
Comment on lines
865
to
+868
| $proxy = $this->createMock( BigQuery_Proxy_Client::class ); | ||
| $proxy->method( 'query' ) | ||
| ->with( 'conversion_journey_source_mix_subscribers' ) | ||
| ->willReturn( $rows ); | ||
|
|
||
| // Each bucket gets count_completed_orders called once; return 1 for gate | ||
| // (2 rows), 1 for prompt (1 row), 1 for direct (1 row). | ||
| $resolver = $this->createMock( Woo_Order_Resolver::class ); | ||
| $resolver->method( 'count_completed_orders' )->willReturn( 1 ); | ||
| ->willReturn( $bq_rows ); |
Comment on lines
1005
to
+1008
| $proxy = $this->createMock( BigQuery_Proxy_Client::class ); | ||
| $proxy->method( 'query' ) | ||
| ->with( 'conversion_journey_source_mix_donors' ) | ||
| ->willReturn( $rows ); | ||
| ->willReturn( $bq_rows ); |
Comment on lines
+1962
to
+1966
| $proxy->method( 'query' )->willReturnCallback( | ||
| static function ( $query_name ) use ( $map ) { | ||
| return $map[ $query_name ] ?? []; | ||
| } | ||
| ); |
Comment on lines
+2021
to
+2028
| $subs->method( 'get_new_subscriber_records_in_window' )->willReturn( | ||
| [ | ||
| [ | ||
| 'customer_id' => 1, | ||
| 'ts' => 1700000000, | ||
| ], | ||
| ] | ||
| ); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
All Submissions:
Changes proposed in this Pull Request:
Brings five Insights → Conversion Journey (Tab 3) metrics from "coming soon" to live data, built on a WP/Woo identity spine with BigQuery supplying only the conversion source (gate / prompt / direct), attached to each local record by a timestamp-window match — no GA cookie is ever cast to a Woo customer ID.
4.2 / 4.3 / 4.4 always use all available history regardless of the selected date range (a caption now says so on each); 3.2 / 3.3 follow the dashboard date range. This is primarily a backend change plus that one caption — the chart components and response types were already in place.
Part of NPPD-1692.
How to test the changes in this Pull Request:
plugins/newspack-plugin:n test-php --filter Test_Conversion_Metric(expect 87 passing) andn test-php --group insights(no regressions).npm test -- HowLongConversionsTakeSection— the new test asserts the all-history caption renders on exactly the three snapshot charts (4.2 / 4.3 / 4.4), not on 4.1.plugins/newspack-plugin,./vendor/bin/phpcs includes/wizards/insights/storage includes/wizards/insights/metricsandnpm run lint:js -- src/wizards/insights/tabs/conversion/HowLongConversionsTakeSection.tsx— expect no errors.*_probe_zero_all_directand*_registrations_error_all_directunit tests).newspack-manager-client, not the hub).Other information:
Notes for reviewers: BigQuery
event_timestampis microseconds — converted to seconds before timestamp matching. Storage epochs are built in PHP from UTC datetime strings (not SQLUNIX_TIMESTAMP, which would use the session timezone). The newrows_to_records/rows_to_lagshelpers are duplicated per storage class to match the existing self-contained convention (no shared base;id_list/fmtare likewise duplicated).Woo_Order_Resolveris intentionally left in place — it still backs the deferred influenced metrics and is removed in a later PR. Woo SQL bodies are live-verified rather than unit-tested (no WooCommerce tables in the PHPUnit bootstrap; Phase A precedent).