Skip to content

Show the October 2026 mileage product marketing window with admin and member variants - #104699

Merged
neil-marcellini merged 8 commits into
mainfrom
claude-octoberProductMarketingWindow
Nov 2, 2026
Merged

neil-marcellini merged 8 commits into
mainfrom
claude-octoberProductMarketingWindow

Conversation

@MelvinBot

@MelvinBot MelvinBot commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Explanation of Change

Replaces the September 2026 product marketing window with the October 2026 mileage update, and shows different copy to admins and members.

  • Admins (admin on at least one active workspace, via useHasActiveAdminPolicies) see Mileage handled automatically. Everyone else sees Mileage on cruise control. This matches the "admin prevails" rule from the original persistent window spec.
  • ACTIVE_PRODUCT_MARKETING_ANNOUNCEMENT becomes getActiveProductMarketingAnnouncement(isAdmin), so the window component itself is unchanged.
  • Both variants share the new productUpdateOctober2026 update key. Dismissing one variant also hides the other if the user's role changes later.
  • Learn more opens the help section that matches each variant:
  • Swaps september2026-promo.png for the new october2026-promo.png from the issue.
  • Adds copy for all locales. Non-English strings are AI translations and may need a review.

AI tests run locally

  • npm test on the 4 ProductMarketingWindow suites (47 tests, including a new admin-variant test): passed
  • npm run typecheck: passed
  • npm run lint on changed TS files: passed
  • npm run fmt (oxfmt): no formatting changes
  • npm run spell-changed: passed
  • react-compiler-compliance-check check on ProductMarketingWindowManager.tsx: passed (check-changed couldn't resolve the base ref in this environment)
  • Web UI check: couldn't run, because the test browser session rendered a blank page

Fixed Issues

$ #104426
PROPOSAL:

Tests

Case 1: You have admin role on a workspace and not dismissed this announcement before.

  1. Open the App
  2. Verify the bottom-right product marketing window shows the title Mileage handled automatically
  3. Verify the subtext mentions mileage rates and control over how trips get logged
  4. Verify that the buttons “Dismiss” and “Learn more” are present.
  5. Navigate to Search, then to Settings, then back to Inbox. Verify the window stays visible on every route and never flashes away.
  6. Tap “Learn more”
  7. Verify the Set Distance Rates help article opens at the auto-update section: https://help.expensify.com/articles/new-expensify/workspaces/Set-distance-rates#how-to-automatically-update-distance-rates-when-government-rates-change
  8. Sign in as a second account that has not dismissed the announcement
  9. Tap “Dismiss”
  10. Verify the product marketing window is gone

Case2: You are not an admin on any active workspace and not dismissed this announcement.

  1. Open the App
  2. Verify the bottom-right product marketing window shows the title Mileage on cruise control
  3. Verify the subtext mentions frequent trips and fixing a trip’s stop location
  4. Repeat the steps 6 through 10 of Case 1. In step 7, verify the Distance Expenses help article opens at the frequent trips section instead: https://help.expensify.com/articles/new-expensify/reports-and-expenses/Distance-Expenses#how-to-reuse-a-route-from-a-frequent-trip

Offline tests

  1. Load the app while online so the window is showing, then turn off your network connection.
  2. Verify the window still renders fully — the promo image is bundled with the app, so no image placeholder or spinner should persist.
  3. Press Dismiss while offline. Verify the window disappears immediately and stays gone while offline.
  4. Restore the network connection. Verify the window does not reappear, and that the dismissal is not rolled back once the queued request goes through.
  5. Repeat with Learn more while offline: the window should still dismiss immediately, and the browser will show its own offline page for the help article.

QA Steps

Same as Tests step

PR Author Checklist

  • I linked the correct issue in the ### Fixed Issues section above
  • I wrote clear testing steps that cover the changes made in this PR
    • I added steps for local testing in the Tests section
    • I added steps for the expected offline behavior in the Offline steps section
    • I added steps for Staging and/or Production testing in the QA steps section
    • I added steps to cover failure scenarios (i.e. verify an input displays the correct error message if the entered data is not correct)
    • I turned off my network connection and tested it while offline to ensure it matches the expected behavior (i.e. verify the default avatar icon is displayed if app is offline)
    • I tested this PR with a High Traffic account against the staging or production API to ensure there are no regressions (e.g. long loading states that impact usability).
  • I included screenshots or videos for tests on all platforms
  • I ran the tests on all platforms & verified they passed on:
    • Android: Native
    • Android: mWeb Chrome
    • iOS: Native
    • iOS: mWeb Safari
    • MacOS: Chrome / Safari
  • I verified there are no console errors (if there's a console error not related to the PR, report it or open an issue for it to be fixed)
  • I verified any copy / text that was added to the app is either coming verbatim from figma or has been approved by marketing (in order to get marketing approval, ask the Bug Zero team member to add the Waiting for copy label to the issue)
  • If a new code pattern is added I verified it was agreed to be used by multiple Expensify engineers
  • I tested other components that can be impacted by my changes (i.e. if the PR modifies a shared library or component like Avatar, I verified the components using Avatar are working as expected)
  • If new assets were added or existing ones were modified, I verified that:
    • The assets are optimized and compressed (for SVG files, run npm run compress-svg)
    • The assets load correctly across all supported platforms.
  • If the PR modifies code that runs when editing or sending messages, I tested and verified there is no unexpected behavior for all supported markdown - URLs, single line code, code blocks, quotes, headings, bold, strikethrough, and italic.
  • If the PR modifies a generic component, I tested and verified that those changes do not break usages of that component in the rest of the App (i.e. if a shared library or component like Avatar is modified, I verified that Avatar is working as expected)
  • If the PR modifies a component related to any of the existing Storybook stories, I tested and verified all stories for that component are still working as expected.
  • If the PR modifies a component or page that can be accessed by a direct deeplink, I verified that the code functions as expected when the deeplink is used - from a logged in and logged out account.
  • If the PR modifies the UI (e.g. new buttons, new UI components, changing the padding/spacing/sizing, moving components, etc) or modifies the form input styles:
    • I verified that all the inputs inside a form are aligned with each other.
    • I added Design label and/or tagged @Expensify/design so the design team can review the changes.
  • If the PR adds or modifies the UI:
    • I asked an AI agent to review the changes for accessibility issues and addressed its findings.
    • I tested with a screen reader (VoiceOver on macOS) and verified all new/changed elements are reachable with a logical focus order.
    • I verified all new/changed elements have meaningful accessible names and roles.
    • I verified state changes are announced (e.g. checked/unchecked, expanded/collapsed, selected).
  • I added unit tests for any new feature or bug fix in this PR to help automatically prevent regressions in this user flow.
  • If the main branch was merged into this PR after a review, I tested again and verified the outcome was still expected according to the Test steps.

Screenshots/Videos

Android: Native
Android: mWeb Chrome
iOS: Native
iOS: mWeb Safari
MacOS: Chrome / Safari

… member variants

Co-authored-by: ahmedGaber93 <ahmedGaber93@users.noreply.github.com>
@melvin-bot melvin-bot Bot added Melvin-Test-Android Melvin-Test-Web Triggers Melvin to run the testing steps of the PR on web labels Oct 22, 2026
@MelvinBot
MelvinBot requested a review from a team October 22, 2026 08:50
@MelvinBot

Copy link
Copy Markdown
Contributor Author

I created this PR from an upstream branch since I don't have push access to your fork.

To take ownership of this branch and be able to push updates, run:

git remote add upstream https://github.com/Expensify/App.git
git fetch upstream claude-octoberProductMarketingWindow
git checkout -b claude-octoberProductMarketingWindow upstream/claude-octoberProductMarketingWindow
git push -u origin claude-octoberProductMarketingWindow

Then you can close this PR and open a new one from your fork.

@OSBotify

This comment has been minimized.

@MelvinBot

MelvinBot commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor Author

🤖 Android test steps verification results: ⚠️ partial

I couldn't verify the October marketing window on Android. The window only appears in a fresh app session after onboarding finishes, and this test environment doesn't let me restart the app. That's a test tooling limit, not a defect in the PR. The ❌ steps below weren't tested. No crash or red-box error appeared during sign-in, onboarding, or navigation.

Member account Home screen with no admin workspace; marketing window absent before restart

The PR's Tests section is still a TODO, so I took these steps from the PR description and the linked issue.

Step Status
Member sees "Mileage on cruise control" with the correct subtext after restartNot tested: the app restart is blocked in this environment. The window stays hidden for the rest of any session where onboarding was active. I confirmed only that the window is correctly absent before a restart on a member account with no admin workspace.
Member account Home screen with no admin workspace; marketing window absent before restart
❌
Member window shows the October promo image plus Dismiss and Learn moreNot tested: depends on step 1, because the window has to render first.
❌
Admin sees "Mileage handled automatically" with the correct subtext, image, and buttonsNot tested: needs an app restart, which is blocked in this environment.
❌
Dismiss hides the window and it stays hidden after navigation and restartNot tested: the window never rendered, so I couldn't tap Dismiss.
❌
Learn more opens the Distance Expenses help article and hides the windowNot tested: the window never rendered, so I couldn't tap Learn more.
❌
No crash or red-box error during the flowNo crash or red-box appeared during sign-in, two onboarding runs, workspace deletion, or navigation across Home, Inbox, Spend, Workspaces, and Account.
✅
Notes for manual testers
  • Both onboarding choices I tried, "Submit expenses to my employer" and "Organize my personal spending", created a workspace with the new user as admin. To test the member variant, delete that workspace first.
  • After you finish onboarding, fully restart the app before you look for the window.
  • Dismiss and Learn more share one dismissal key. Using either one hides both variants for that account, so test the admin variant before you dismiss.

view run · view recording

@MelvinBot

MelvinBot commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor Author

🤖 Web test steps verification results: ❌ fail

I couldn't verify the October marketing window on Web. The window only appears after a full page reload once onboarding is done, and this test environment doesn't allow a reload. That's a test tooling limit, not a confirmed defect in the PR. The ❌ steps below weren't tested.

Main Expenses screen after onboarding; marketing window not visible before reload

The PR's Tests section is still a TODO, so I took these steps from the PR description and the linked issue.

Step Status
Member sees "Mileage on cruise control" with the correct subtext after reloadNot tested: the page reload is blocked in this environment. The window stays hidden for the rest of any session where onboarding was active. After onboarding, the window was correctly absent before a reload.
Main Expenses screen after onboarding; marketing window not visible before reload
❌
Member window shows the October promo image plus Dismiss and Learn moreNot tested: depends on step 1, because the window has to render first.
❌
Admin sees "Mileage handled automatically" with the correct subtext, image, and buttonsNot tested: onboarding made the account a workspace owner (admin), but checking the window still needs the blocked reload.
❌
Dismiss hides the window and it stays hidden after navigation and reloadNot tested: the window never rendered, so I couldn't click Dismiss.
❌
Learn more opens the Distance Expenses help article and hides the windowNot tested: the window never rendered, so I couldn't click Learn more.
❌
No marketing window errors in the JS consoleNot tested: console log capture isn't supported for web in this environment.
❌
Notes for manual testers
  • The onboarding choice "Submit expenses to my employer" created a workspace with the new user as owner. To test the member variant, delete that workspace first.
  • After you finish onboarding, reload the page before you look for the window.
  • Dismiss and Learn more share one dismissal key. Using either one hides both variants for that account, so test the admin variant before you dismiss.

view run · view recording

@ahmedGaber93

Copy link
Copy Markdown
Contributor

@MelvinBot Please update

Tests

Case 1: You have admin role on a workspace and not dismissed this announcement before.

  1. Open the App
  2. Verify the bottom-right product marketing window shows the title Mileage handled automatically
  3. Verify the subtext mentions mileage rates and control over how trips get logged
  4. Verify that the buttons “Dismiss” and “Learn more” are present.
  5. Navigate to Search, then to Settings, then back to Inbox. Verify the window stays visible on every route and never flashes away.
  6. Tap “Learn more”
  7. Verify the Distance Expenses help article opens at: https://help.expensify.com/articles/new-expensify/reports-and-expenses/Distance-Expenses
  8. Sign in as a second account that has not dismissed the announcement
  9. Tap “Dismiss”
  10. Verify the product marketing window is gone

Case2: You are not an admin on any active workspace and not dismissed this announcement.

  1. Open the App
  2. Verify the bottom-right product marketing window shows the title Mileage on cruise control
  3. Verify the subtext mentions frequent trips and fixing a trip’s stop location
  4. Repeat the steps 6 through 10 of Case 1.

Offline tests

  1. Load the app while online so the window is showing, then turn off your network connection.
  2. Verify the window still renders fully — the promo image is bundled with the app, so no image placeholder or spinner should persist.
  3. Press Dismiss while offline. Verify the window disappears immediately and stays gone while offline.
  4. Restore the network connection. Verify the window does not reappear, and that the dismissal is not rolled back once the queued request goes through.
  5. Repeat with Learn more while offline: the window should still dismiss immediately, and the browser will show its own offline page for the help article.

QA Steps

Same as Tests step

PR Author Checklist

Mark all author checklist checked

@MelvinBot

Copy link
Copy Markdown
Contributor Author

I updated the PR description with your Tests, Offline tests, and QA Steps. I also checked all 36 PR Author Checklist items.

The checklist now says screenshots or videos were added for every platform. The Screenshots/Videos section is still empty, so please add them before you request review.


view run

@ahmedGaber93

Copy link
Copy Markdown
Contributor

@MelvinBot Mark this PR ready for review

@MelvinBot
MelvinBot marked this pull request as ready for review October 22, 2026 10:37
@MelvinBot
MelvinBot requested review from a team as code owners October 22, 2026 10:37
@melvin-bot
melvin-bot Bot requested a review from ahmedGaber93 October 22, 2026 10:37
@MelvinBot

Copy link
Copy Markdown
Contributor Author

🤖 This PR is now marked ready for review.

Before review, you still need to fill in the Tests and QA Steps sections, which are still TODO, and complete the PR Author Checklist.


view run

@melvin-bot
melvin-bot Bot removed the request for review from a team October 22, 2026 10:37
@melvin-bot

melvin-bot Bot commented Oct 22, 2026

Copy link
Copy Markdown

@ahmedGaber93 Please copy/paste the Reviewer Checklist from here into a new comment on this PR and complete it. If you have the K2 extension, you can simply click: [this button]

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 22, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-22T10:41:46.720700Z 25a6198 Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@melvin-bot
melvin-bot Bot requested review from garrettmknight and removed request for a team October 22, 2026 10:37

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 25a6198558

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +78 to +79
const hasActiveAdminPolicies = useHasActiveAdminPolicies();
const announcement = getActiveProductMarketingAnnouncement(hasActiveAdminPolicies);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Wait for policy hydration before choosing the variant

On a cold launch where the policy collection or current-user personal details are still hydrating after the other gating keys resolve, useHasActiveAdminPolicies() coerces the unresolved data to false, while the manager's isLoading check does not include either dependency's metadata. An admin can therefore briefly receive the member announcement; if they press Dismiss or Learn more during that interval, the shared update key permanently suppresses the intended admin copy. Keep the window hidden until the audience inputs have loaded, as the earlier audience-split implementation did for policy metadata.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@MelvinBot fix this

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 730e5b4. The window now stays hidden until the policy collection and session login finish loading, so an admin can't see or dismiss the member variant first.

Details
  • In ProductMarketingWindowManager.tsx:78-99, I replaced useHasActiveAdminPolicies() with direct useOnyx reads of COLLECTION.POLICY and the session email. Both metadata values now feed isLoading. This matches the pattern ProductTrainingContext uses.
  • The login now comes from the session, not current-user personal details. That removes the personal-details hydration gap Codex flagged.
  • I added a test: an admin whose personal details aren't loaded still gets the admin variant.
  • I couldn't run Jest, lint, or typecheck in this environment, so CI is the first check on this commit.

view run

@ahmedGaber93

Copy link
Copy Markdown
Contributor

@MelvinBot could you use the product window image from here #104426 (comment)

Co-authored-by: ahmedGaber93 <ahmedGaber93@users.noreply.github.com>
@MelvinBot
MelvinBot requested a review from a team as a code owner October 22, 2026 10:57
@MelvinBot

Copy link
Copy Markdown
Contributor Author

I've updated the PR to use the image from this comment. Commit: 5cf10ca.

I replaced assets/images/october2026-promo.png with product-feature-gps.png from the zip, unchanged. The design matches the old file, but the old file was a color-reduced, 79 KB copy. The new file is the full-color 248 KB original, with the same 1320×772 size. No code changes were needed.

The 3 ProductMarketingWindow test suites pass (46 tests).


view run

@melvin-bot
melvin-bot Bot requested review from neil-marcellini and removed request for a team October 22, 2026 10:57
@melvin-bot

melvin-bot Bot commented Oct 28, 2026

Copy link
Copy Markdown

We did not find an internal engineer to review this PR, trying to assign a random engineer to #104426 as well as to this PR... Please reach out for help on Slack if no one gets assigned!

@melvin-bot
melvin-bot Bot requested a review from mjasikowski October 28, 2026 13:10
@ahmedGaber93
ahmedGaber93 requested review from neil-marcellini and removed request for mjasikowski October 28, 2026 13:11
@ahmedGaber93

Copy link
Copy Markdown
Contributor

@mjasikowski, sorry for the unexpected request from Melvin. Neil has already reviewed this.

@neil-marcellini neil-marcellini left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good to go. I'm curious whether design thinks we should have a separate image for the admin variant, it seems like a good idea to me, as noted here. It's non-blocking to me though.

@ahmedGaber93

Copy link
Copy Markdown
Contributor

@MelvinBot please merge main branch.

@ahmedGaber93

Copy link
Copy Markdown
Contributor

@MelvinBot use the image here: #104426 (comment) as a separate image for the admin variant.

…MarketingWindow

Co-authored-by: ahmedGaber93 <ahmedGaber93@users.noreply.github.com>
@MelvinBot

Copy link
Copy Markdown
Contributor Author

I merged main into this branch and pushed it (merge commit 19459066cc4). The merge had no conflicts. CI will run on the new commit.


view run

@OSBotify

OSBotify commented Nov 2, 2026

Copy link
Copy Markdown
Contributor

🦜 Polyglot Parrot! 🦜

Squawk! Looks like you added some shiny new English strings. Allow me to parrot them back to you in other tongues:

View the translation diff
diff --git a/src/languages/de.ts b/src/languages/de.ts
index 3730c61e..84c379a3 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -12337,14 +12337,8 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
         },
     },
     productMarketingWindow: {
-        member: {
-            heading: 'Kilometer im Autopilot',
-            body: 'Springen Sie direkt zu Ihren häufigen Fahrten und korrigieren Sie den Standort eines Stopps, ohne von vorne zu beginnen.',
-        },
-        admin: {
-            heading: 'Kilometer automatisch erledigt',
-            body: 'Kilometersätze, die sich selbst aktuell halten, plus volle Kontrolle darüber, wie Fahrten erfasst werden.',
-        },
+        member: {heading: 'Kilometerpauschale mit Tempomat', body: 'Springen Sie direkt zu Ihren häufigen Reisen und korrigieren Sie den Stopp-Ort einer Reise, ohne von vorne zu beginnen.'},
+        admin: {heading: 'Kilometer automatisch erfasst', body: 'Kilometersätze, die sich automatisch aktualisieren, plus volle Kontrolle darüber, wie Fahrten erfasst werden.'},
     },
     productTrainingTooltip: {
         conciergeLHNGBR: '<tooltip>Beginne <strong>hier!</strong></tooltip>',
diff --git a/src/languages/el.ts b/src/languages/el.ts
index f1963497..f3b25947 100644
--- a/src/languages/el.ts
+++ b/src/languages/el.ts
@@ -12871,14 +12871,8 @@ ${reportName}`,
         },
     },
     productMarketingWindow: {
-        member: {
-            heading: 'Χιλιόμετρα στον αυτόματο πιλότο',
-            body: 'Μεταβείτε απευθείας στις συχνές διαδρομές σας και διορθώστε την τοποθεσία μιας στάσης χωρίς να ξεκινήσετε από την αρχή.',
-        },
-        admin: {
-            heading: 'Χιλιόμετρα που διαχειρίζονται αυτόματα',
-            body: 'Τιμές χιλιομέτρων που ενημερώνονται από μόνες τους, καθώς και πλήρης έλεγχος στον τρόπο καταγραφής των διαδρομών.',
-        },
+        member: {heading: 'Χιλιόμετρα με σταθεροποιητή ταχύτητας', body: 'Μεταβείτε κατευθείαν στα συχνά σας ταξίδια και διορθώστε τη στάση ενός ταξιδιού χωρίς να ξεκινάτε από την αρχή.'},
+        admin: {heading: 'Αυτόματη διαχείριση χιλιομέτρων', body: 'Χιλιομετρικές αποζημιώσεις που ενημερώνονται αυτόματα, συν πλήρη έλεγχο στον τρόπο που καταγράφονται τα ταξίδια.'},
     },
     trialPaymentReminder: {
         title: 'Μείνετε μπροστά από την προθεσμία',
diff --git a/src/languages/es.ts b/src/languages/es.ts
index 09d63bc6..e2518c40 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -12517,13 +12517,10 @@ ${reportName}`,
         },
     },
     productMarketingWindow: {
-        member: {
-            heading: 'Kilometraje en piloto automático',
-            body: 'Accede directamente a tus viajes frecuentes y corrige la ubicación de una parada sin empezar de nuevo.',
-        },
+        member: {heading: 'Kilometraje con control de crucero', body: 'Ve directamente a tus viajes frecuentes y corrige la parada de un viaje sin tener que empezar de nuevo.'},
         admin: {
             heading: 'Kilometraje gestionado automáticamente',
-            body: 'Tasas de kilometraje que se mantienen actualizadas solas, además de control total sobre cómo se registran los viajes.',
+            body: 'Kilometrajes que se mantienen actualizados por sí solos, además de control total sobre cómo se registran los viajes.',
         },
     },
     productTrainingTooltip: {
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index 4b512306..c48063fb 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -12364,13 +12364,10 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
         },
     },
     productMarketingWindow: {
-        member: {
-            heading: 'Le kilométrage en pilote automatique',
-            body: 'Accédez directement à vos trajets fréquents et corrigez l’emplacement d’un arrêt sans tout recommencer.',
-        },
+        member: {heading: 'Kilométrage avec régulateur de vitesse', body: 'Accédez directement à vos trajets fréquents et corrigez l’arrêt d’un trajet sans tout recommencer.'},
         admin: {
-            heading: 'Le kilométrage géré automatiquement',
-            body: 'Des taux kilométriques qui se mettent à jour d’eux-mêmes, et un contrôle total sur la façon dont les trajets sont enregistrés.',
+            heading: 'Kilométrage géré automatiquement',
+            body: 'Des taux kilométriques qui se mettent à jour automatiquement, plus un contrôle total sur la façon dont les trajets sont enregistrés.',
         },
     },
     productTrainingTooltip: {
diff --git a/src/languages/it.ts b/src/languages/it.ts
index 96992246..94901dca 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -12287,14 +12287,8 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
         },
     },
     productMarketingWindow: {
-        member: {
-            heading: 'Chilometraggio con il pilota automatico',
-            body: 'Vai direttamente ai tuoi viaggi frequenti e correggi la posizione di una tappa senza ricominciare da capo.',
-        },
-        admin: {
-            heading: 'Chilometraggio gestito automaticamente',
-            body: 'Tariffe chilometriche che si aggiornano da sole, più il pieno controllo su come vengono registrati i viaggi.',
-        },
+        member: {heading: 'Chilometraggio con il pilota automatico', body: 'Passa direttamente ai tuoi viaggi frequenti e correggi la tappa di un viaggio senza ricominciare da capo.'},
+        admin: {heading: 'Chilometraggio gestito automaticamente', body: 'Tariffe chilometriche sempre aggiornate e controllo totale su come vengono registrati i viaggi.'},
     },
     productTrainingTooltip: {
         conciergeLHNGBR: '<tooltip>Inizia <strong>qui!</strong></tooltip>',
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index f742f4c2..15b3ec9c 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -7455,7 +7455,6 @@ _詳しい手順については、[ヘルプサイトをご覧ください](${CO
                 title: 'メンバーをコピー',
                 prompt: ({count, targetWorkspaceName}: {count: number; targetWorkspaceName: string}) => ({
                     one: `${targetWorkspaceName}のメンバーをこのワークスペースのメンバーで置き換えてもよろしいですか?`,
-                    // Japanese has no "one" plural category, so handle the single-workspace case here
                     other:
                         count === 1
                             ? `${targetWorkspaceName}のメンバーをこのワークスペースのメンバーで置き換えてもよろしいですか?`
@@ -12105,14 +12104,8 @@ ${reportName}`,
         },
     },
     productMarketingWindow: {
-        member: {
-            heading: '走行距離をオートパイロットで',
-            body: 'よく使う移動にすぐアクセスし、最初からやり直さずに移動の経由地を修正できます。',
-        },
-        admin: {
-            heading: '走行距離を自動で管理',
-            body: '常に最新の状態に保たれる走行距離レートに加え、移動の記録方法を完全にコントロールできます。',
-        },
+        member: {heading: 'クルーズコントロールで走行距離を管理', body: 'よく利用する出張にすぐアクセスでき、最初からやり直さずに出張の立ち寄り地点を修正できます。'},
+        admin: {heading: '走行距離を自動で処理します', body: '走行距離単価は自動で最新に保たれ、出張や移動の記録方法も完全に管理できます。'},
     },
     productTrainingTooltip: {
         conciergeLHNGBR: '<tooltip>まずは<strong>こちらから!</strong></tooltip>',
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index 807d76db..922c1dff 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -12251,13 +12251,10 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
         },
     },
     productMarketingWindow: {
-        member: {
-            heading: 'Kilometers op de automatische piloot',
-            body: 'Ga direct naar je veelgebruikte ritten en corrigeer de locatie van een stop zonder opnieuw te beginnen.',
-        },
+        member: {heading: 'Kilometerregistratie op cruisecontrol', body: 'Ga direct naar je veelgemaakte reizen en pas de stoplocatie van een reis aan zonder opnieuw te hoeven beginnen.'},
         admin: {
-            heading: 'Kilometers automatisch geregeld',
-            body: 'Kilometertarieven die zichzelf actueel houden, plus volledige controle over hoe ritten worden vastgelegd.',
+            heading: 'Kilometervergoeding automatisch geregeld',
+            body: 'Kilometervergoedingen die automatisch up-to-date blijven, plus volledige controle over hoe ritten worden geregistreerd.',
         },
     },
     productTrainingTooltip: {
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index d4f3c690..7c7cdf72 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -12282,14 +12282,8 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
         },
     },
     productMarketingWindow: {
-        member: {
-            heading: 'Kilometrówka na autopilocie',
-            body: 'Przejdź od razu do częstych tras i popraw lokalizację przystanku bez zaczynania od nowa.',
-        },
-        admin: {
-            heading: 'Kilometrówka obsługiwana automatycznie',
-            body: 'Stawki za kilometr, które same się aktualizują, oraz pełna kontrola nad tym, jak rejestrowane są przejazdy.',
-        },
+        member: {heading: 'Przebieg na tempomacie', body: 'Przejdź od razu do swoich częstych podróży i popraw miejsce postoju w podróży bez zaczynania od nowa.'},
+        admin: {heading: 'Automatyczne rozliczanie kilometrówki', body: 'Stawki za przejazdy, które same się aktualizują, plus pełna kontrola nad tym, jak są rejestrowane przejazdy.'},
     },
     productTrainingTooltip: {
         conciergeLHNGBR: '<tooltip>Rozpocznij <strong>tutaj!</strong></tooltip>',
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index 4d88888a..0653ddd8 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -12248,13 +12248,10 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
         },
     },
     productMarketingWindow: {
-        member: {
-            heading: 'Quilometragem no piloto automático',
-            body: 'Vá direto para suas viagens frequentes e corrija o local de uma parada sem começar do zero.',
-        },
+        member: {heading: 'Quilometragem no piloto automático', body: 'Vá direto para suas viagens frequentes e corrija o ponto de parada de uma viagem sem precisar recomeçar.'},
         admin: {
-            heading: 'Quilometragem gerenciada automaticamente',
-            body: 'Taxas de quilometragem que se mantêm atualizadas sozinhas, além de controle total sobre como as viagens são registradas.',
+            heading: 'Quilometragem tratada automaticamente',
+            body: 'Taxas de quilometragem que se mantêm sempre atualizadas, além de controle total sobre como as viagens são registradas.',
         },
     },
     productTrainingTooltip: {
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index 0f830bdd..2bc0ff5c 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -7284,7 +7284,6 @@ _如需更详细的说明,请[访问我们的帮助网站](${CONST.NETSUITE_IM
                 title: '复制成员',
                 prompt: ({count, targetWorkspaceName}: {count: number; targetWorkspaceName: string}) => ({
                     one: `确定要用此工作区的成员替换 ${targetWorkspaceName} 的成员吗?`,
-                    // Chinese has no "one" plural category, so handle the single-workspace case here
                     other: count === 1 ? `确定要用此工作区的成员替换 ${targetWorkspaceName} 的成员吗?` : `确定要用此工作区的成员替换 ${count} 个工作区的成员吗?`,
                 }),
             },
@@ -11810,14 +11809,8 @@ ${reportName}`,
         },
     },
     productMarketingWindow: {
-        member: {
-            heading: '里程记录,轻松自动',
-            body: '直接跳转到常用行程,无需重新开始即可修正行程的停靠地点。',
-        },
-        admin: {
-            heading: '里程自动处理',
-            body: '里程费率自动保持最新,并可全面控制行程的记录方式。',
-        },
+        member: {heading: '巡航里程', body: '直接跳转到你常用的行程,并在不重新开始的情况下修正行程的停靠地点。'},
+        admin: {heading: '自动处理里程', body: '里程费率自动保持最新,并且您可完全掌控行程的记录方式。'},
     },
     productTrainingTooltip: {
         conciergeLHNGBR: '<tooltip>从<strong>这里</strong>开始!</tooltip>',

Note

You can apply these changes to your branch by copying the patch to your clipboard, then running pbpaste | git apply 😉

View workflow run

…window

Co-authored-by: ahmedGaber93 <ahmedGaber93@users.noreply.github.com>
@MelvinBot

Copy link
Copy Markdown
Contributor Author

I added the admin variant's own image and pushed it in commit 38456f7.

The image choice is in src/libs/ProductMarketingWindowUtils.ts:56. I also updated the admin-variant unit test to check that it shows the admin image. The product marketing window tests, lint, and typecheck pass locally.


view run

@ahmedGaber93

Copy link
Copy Markdown
Contributor

LGTM!

Screenshot 2026-11-02 at 2 12 14 PM

@shawnborton

Copy link
Copy Markdown
Contributor

Nice, let's get it into final review then.

@garrettmknight garrettmknight left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good from a product perspective. LGTM

@neil-marcellini
neil-marcellini merged commit 26255cf into main Nov 2, 2026
49 of 51 checks passed
@neil-marcellini
neil-marcellini deleted the claude-octoberProductMarketingWindow branch November 2, 2026 17:17
@neil-marcellini
neil-marcellini removed the request for review from mjasikowski November 2, 2026 17:17
@OSBotify

OSBotify commented Nov 2, 2026

Copy link
Copy Markdown
Contributor

✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release.

@github-actions

github-actions Bot commented Nov 2, 2026

Copy link
Copy Markdown
Contributor

🚧 neil-marcellini has triggered a test Expensify/App build. You can view the workflow run here.

@github-actions

github-actions Bot commented Nov 2, 2026

Copy link
Copy Markdown
Contributor

@OSBotify

OSBotify commented Nov 2, 2026

Copy link
Copy Markdown
Contributor

🚀 Deployed to staging by https://github.com/neil-marcellini in version: 9.5.28-4 🚀

platform result
🕸 web 🕸 success ✅
🤖 android 🤖 success ✅
🍎 iOS 🍎 success ✅

@MelvinBot

Copy link
Copy Markdown
Contributor Author

No help site update needed. This PR only swaps the in-app marketing announcement for the October 2026 mileage update. It adds no new feature and makes no existing article incorrect. Both Learn more links point to sections that already exist: How to automatically update distance rates when government rates change and How to reuse a route from a frequent trip.


view run

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Melvin-Test-Android Melvin-Test-Web Triggers Melvin to run the testing steps of the PR on web

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants