Skip to content

Submit the guest order tracking form with POST - #1097

Merged
tblivet merged 2 commits into
PrestaShop:2.xfrom
boo-code:fix/guest-tracking-form-post-13911
Sep 21, 2026
Merged

tblivet merged 2 commits into
PrestaShop:2.xfrom
boo-code:fix/guest-tracking-form-post-13911

Conversation

@boo-code

@boo-code boo-code commented Sep 3, 2026 •

Copy link
Copy Markdown
Contributor
Questions Answers
Description? The guest order tracking form is submitted with GET, so the shopper's email address ends up in the URL. It is then recorded by analytics as a page path, kept in the browser history, and written to the access log and any referrer. Submitting it with POST keeps the address out of the URL, and the account transformation form on the tracking page now carries the order lookup itself.
Type? bug fix
BC breaks? no
Deprecations? no
Fixed ticket? PrestaShop/PrestaShop#13911
Sponsor company -
How to test? See below.

Why

templates/customer/guest-login.tpl submits the tracking form with method="get", and the form holds a
field named email. Submitting it therefore produces a URL of the shape
/guest-tracking?order_reference=...&email=someone@example.com.

That is the report in PrestaShop/PrestaShop#13911: email addresses visible in Google Analytics page
paths. A URL carrying the address does not only reach analytics - it is also kept in the browser history,
written to the web server access log, and sent as the referrer to anything the page loads.

What it does

Switches the form to method="post".

Tools::getValue() reads $_POST before $_GET (classes/Tools.php), and GuestTrackingController
reads order_reference and email through it, so no controller change is needed. Links that already
carry the parameters in a query string keep working, since the controller still accepts them.

The hidden controller input is left in place. It exists because a GET form replaces the action's query
string with its own fields; with POST the action's query string is preserved and the input is simply
harmless.

The account transformation form

customer/_partials/account-transformation-form.tpl posts back to the page URL with only the password. With
the lookup in the query string that URL carried order_reference and email; once the lookup is posted it
does not, so GuestTrackingController::postProcess() returned at its empty-input check and the shopper was sent
back to the lookup form with no message. guest-tracking.tpl now passes both to the partial, which posts them as
hidden fields. Order confirmation includes the same partial without them and resolves the order from the cart, so
it renders nothing extra there.

How to test

  1. Front office, open the guest order tracking page.
  2. Fill in an order reference and an email, submit.
  3. Before: the address bar shows ...&email=someone@example.com. After: the URL carries no email.
  4. A link that already carries ?order_reference=...&email=... still resolves the order.
  5. For a guest order, submit a weak password in the "Save time on your next order" form. Before: the lookup form
    comes back with no message. After: "Your password length must be between 8 and 72" (or the score message),
    and a valid password converts the guest into a customer account.

@tblivet

tblivet commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

Hi @boo-code, good finding!
But there's a blocker.

Guest → customer account transformation breaks. account-transformation-form.tpl posts to the document URL with no action, sending only the password. Under GET, order_reference and email were still in the URL and under POST they're gone, so GuestTrackingController::postProcess() returns at the empty-input guard before reaching the transform branch.

To reproduce → look up a guest order, then submit a weak password. Expected something like "Customer password is too weak" actual is a silent redirect back to the tracking form.

Fix → Pass order_reference/email into the form as include parameters from guest-tracking.tpl, rather than reading them inside the partial. The partial is shared with order-confirmation.tpl, where $guest_email isn't assigned and the order is resolved from the cart instead, so wrap the hidden inputs in {if isset(...)} and that page renders nothing extra.

Also worth adding while you're there: that password field has no strength meter, though core gates it with Validate::isAcceptablePasswordScore().

Have a working patch locally if useful 👍

@tblivet
tblivet marked this pull request as ready for review September 15, 2026 09:48
@github-project-automation github-project-automation Bot moved this to Ready for review in PR Dashboard Sep 15, 2026
The form carries the shopper's email address, and submitting it with GET puts
that address in the URL. It is then recorded by analytics as a page path, kept
in the browser history and written to the access log and any referrer.

The controller reads the fields with Tools::getValue(), which takes POST as
well, so no controller change is needed and links that already carry the
parameters in a query string keep working.
The transformation form posts back to the page URL, and with the tracking
form posted that URL no longer carries order_reference and email, so the
controller returned before reaching the transformation and the shopper was
sent back to the lookup form with no message. The tracking page now passes
both to the partial, which posts them as hidden fields. Order confirmation
includes the same partial without them and is unchanged.
@boo-code
boo-code force-pushed the fix/guest-tracking-form-post-13911 branch from d07b504 to d389aae Compare September 21, 2026 10:42
@boo-code
boo-code changed the base branch from develop to 2.x September 21, 2026 10:42
@boo-code

Copy link
Copy Markdown
Contributor Author

@tblivet Fixed the way you describe: guest-tracking.tpl passes order_reference and guest_email to the partial, which posts them as hidden fields inside {if isset(...)}, so order confirmation renders nothing extra. Checked on a 9.2 shop with a guest order: a weak password now gets "Your password length must be between 8 and 72" and a valid one converts the account, while the same POST without the two fields still comes back silent. The PR is also retargeted from develop to 2.x.

The strength meter is not in this change: usePasswordPolicy() binds a [data-ps-ref="password-field"] wrapper with its own hint and feedback markup, so it needs the form-fields.tpl structure rather than the input attributes alone. That is better as its own PR.

@tblivet tblivet 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.

Perfect 👌 Thank you @boo-code !

@ps-jarvis ps-jarvis added the Waiting for QA Status: Action required, Waiting for test feedback label Sep 21, 2026
@ps-jarvis ps-jarvis moved this from Ready for review to To be tested in PR Dashboard Sep 21, 2026
@tblivet

tblivet commented Sep 21, 2026

Copy link
Copy Markdown
Contributor

Thank you @boo-code it's all good 👍


✅ QA approved. PrestaShop 9.3.0, Hummingbird 2.1.0, PHP 8.1.33, front office, Chromium.
AI-assisted QA: an agent drove a real browser through the steps below and drafted this comment. Worth a sanity check.

The five steps were run twice on the same shop: once on the commit this branch started from (a3cdc9ce), once on this branch. A real guest order was placed in each run and looked up.

Before: the lookup left the address bar reading /guest-tracking?controller=guest-tracking&order_reference=WTZQMNHQX&email=<the address>. The reported problem, reproduced.
After: the same lookup lands on /guest-tracking, with no query string at all.

Passing in both runs, so nothing regressed: the order is still found; a link that already carries order_reference and email still resolves it; a password that is too short still answers "Your password length must be between 8 and 72"; a password that is accepted creates an account that can then sign in; and order confirmation still renders the sign-up offer, which is the include that passes no parameters.

One correction to the test plan. Step 5 says that before the fix the lookup form comes back with no message. On the merge base it does not: the message appears there too. That step describes the state between the two commits rather than the state before them, and it does not change the outcome.

Front page, product page and cart answered in both runs, at full width and at 375 and 768 wide, with no console or network errors.

After video:
video.webm

@tblivet tblivet added this to the v2.1.1 milestone Sep 21, 2026
@tblivet tblivet added QA with AI ✓ AI-assisted QA and removed Waiting for QA Status: Action required, Waiting for test feedback labels Sep 21, 2026
@tblivet
tblivet merged commit d2d21b4 into PrestaShop:2.x Sep 21, 2026
11 of 12 checks passed
@github-project-automation github-project-automation Bot moved this from To be tested to Merged in PR Dashboard Sep 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

QA with AI ✓ AI-assisted QA

Projects

Status: Merged

Development

Successfully merging this pull request may close these issues.

3 participants