feat(bf): trial widget + booking link beside the HOST27 deal

On /odoo-black-friday/ the offer row is now two columns at >=901px: the deal (left,
unchanged and still the single dominant primary) with the free trial and a booking
link beside it (right, deliberately smaller and quieter).

- Trial: the existing #trialCard/#trialForm moves verbatim from the features grid into
  the row's aside. Same ids, same static/black-friday.js handler, same consent gate and
  label (AW-18065522009/AtAPCIjjvrAdENn6p6ZD) — no second trial mechanism.
- Booking: a plain <a target=_blank rel=noopener> to Oliver's verified Google
  appointment page (no iframe). Its click fires AW-18065522009/P0j5CPiCv7AdENn6p6ZD
  through the same gate via window.o4pAds.bookConversion; the click is never
  preventDefault-ed, so a blocked tag can never stop the link opening.
- ads-consent.js gains the booking label (from the page, not hard-coded) and the
  bookConversion hook; the buy path is untouched.

Deal buy stays the dominant action; ONE plausible Buy mark; one price; countdown pair
unchanged.
This commit is contained in:
webmaster committed 2026-11-02 09:28:09 +00:00
1 parent 7497fbf588
commit 95d5d455b9
3 files changed
+134 -13

No files matched your search

+104 -13
View File
@@ -284,6 +284,65 @@
text-underline-offset: 3px;
}
/* The offer row: the deal on the left, its two secondary actions (free trial + booking) on
the right. The deal keeps its full width and weight and stays the ONE dominant action;
the right column is deliberately narrower and quieter so the row never reads as three
equal primaries. At 901px and up the row is two columns; below that it stacks, deal
first. Scoped to #offer so the Bootcamp box further down is untouched. */
#offer .container {
grid-template-columns: minmax(0, 620px) minmax(0, 300px);
}
.bf-aside {
display: grid;
gap: 1.25rem;
align-content: start;
}
/* Booking: a quiet, secondary action on its own line — an outlined pill, never a second
brass button. */
.bf-booking {
background: var(--ivory);
border: 1px solid var(--line-brass);
border-radius: var(--radius-lg);
padding: 1.25rem;
text-align: center;
}
.bf-booking h3 {
font-family: Marcellus, Georgia, serif;
font-weight: 400;
font-size: 1rem;
color: var(--midnight);
margin: 0 0 0.35rem;
}
.bf-booking p {
font-size: 0.85rem;
color: var(--ink);
line-height: 1.5;
margin: 0 0 1rem;
}
.bf-booking-link {
display: inline-block;
font-family: Marcellus, Georgia, serif;
font-size: 0.85rem;
letter-spacing: 0.03em;
color: var(--brass-deep);
background: transparent;
border: 1px solid var(--line-brass);
border-radius: var(--radius-pill);
padding: 0.6rem 1.25rem;
text-decoration: none;
transition: background 0.2s, color 0.2s;
}
.bf-booking-link:hover,
.bf-booking-link:focus-visible {
background: var(--brass);
color: var(--midnight);
}
@media (max-width: 900px) {
#offer .container {
grid-template-columns: minmax(0, 620px);
}
}
/* FAQ (native details/summary — no JS) */
.cmp-faq-grid {
display: grid;
@@ -691,6 +750,44 @@
<p class="bf-cta-secondary"><a href="/odoo-hosting-offers/">See everything a year of hosting includes</a></p>
</div>
</div>
<!-- The secondary actions that sit beside the deal: the free trial (moved here from the
features grid, same form, same consent gate) and a booking link. Both are deliberately
smaller and quieter than the deal's buy button, so the row keeps ONE primary action.
The buy stays the dominant, brass, large button in the box on the left. -->
<aside class="bf-aside" aria-label="Other ways to get started">
<!-- Free-trial card: moved verbatim from the features grid. Its id (#trialCard), the
form (#trialForm) and the static/black-friday.js submit handler are unchanged, so it
fires the already-wired Google Ads trial conversion behind the same consent gate —
no second trial mechanism. -->
<div class="feature-card-trial" id="trialCard">
<h3>Free Trial</h3>
<p>Start your 30-day free trial. No credit card required.</p>
<form class="trial-form" id="trialForm">
<input type="email" id="trialEmail" placeholder="Your email address" required />
<select id="trialLocation"></select>
<button type="submit" class="btn btn-brass">Send</button>
</form>
<div class="trial-success" id="trialSuccess">&#10003; Check your inbox to confirm your email address.</div>
</div>
<!-- Booking — a 30-minute call with a named person, NOT "contact us". It opens the
Google appointment page in a NEW TAB (a plain <a>, no iframe: nothing loads until the
visitor chooses to go, so the consent gate on this page is not defeated). Its click
fires the booking conversion through the same consent gate
(window.o4pAds.bookConversion); because the click is never preventDefault-ed, a
blocked tag can never stop the link opening. -->
<div class="bf-booking">
<h3>Prefer to talk first?</h3>
<p>Book a 30-minute call with Oliver, our technical lead, to walk through your setup.</p>
<a
class="bf-booking-link"
id="bookingCTA"
target="_blank"
rel="noopener"
href="https://calendar.google.com/calendar/u/0/appointments/schedules/AcZssZ3DDbaiHFlhNhWySszAQoPXE_H73QLqYT3w7H9IYWC76RA_TgNIhLESjb4N7ep_D2D_OyW9q4-c"
>Book a 30-minute call with Oliver &rarr;</a
>
</div>
</aside>
</div>
</section>
@@ -784,16 +881,8 @@
<h3>Support Bot &amp; Human Support</h3>
<p>AI support bot for instant fixes. Human team for everything else. Your UUID is your key.</p>
</div>
<div class="feature-card-trial" id="trialCard">
<h3>Free Trial</h3>
<p>Start your 30-day free trial. No credit card required.</p>
<form class="trial-form" id="trialForm">
<input type="email" id="trialEmail" placeholder="Your email address" required />
<select id="trialLocation"></select>
<button type="submit" class="btn btn-brass">Send</button>
</form>
<div class="trial-success" id="trialSuccess">&#10003; Check your inbox to confirm your email address.</div>
</div>
<!-- The Free Trial card was moved up beside the Black Friday deal (see #offer), so the
trial widget and the deal sit together. No second card: the same #trialCard/form. -->
</div>
</div>
</section>
@@ -1063,9 +1152,10 @@
<!-- Google Ads consent banner — default DENY. The tag loads only after "Accept".
Markup lives in the page; JS (static/ads-consent.js) reveals it and drives it.
Two conversions are wired here: the buy forms (data-ads-send-to) and the free-trial
form (data-ads-trial-send-to). With JavaScript off it stays hidden and both actions
(the native buy POSTs, the trial's own submit) run untouched.
Three conversions are wired here, all click proxies, all behind this one gate: the buy
forms (data-ads-send-to), the free-trial form (data-ads-trial-send-to) and the booking
link (data-ads-book-send-to). With JavaScript off it stays hidden and every action
(the native buy POSTs, the trial's own submit, the booking <a>) runs untouched.
See wiki/concepts/conversion-tracking-contract. -->
<div
id="adsConsent"
@@ -1075,6 +1165,7 @@
data-ads-id="AW-18065522009"
data-ads-send-to="AW-18065522009/vnDUCPDxt7AdENn6p6ZD"
data-ads-trial-send-to="AW-18065522009/AtAPCIjjvrAdENn6p6ZD"
data-ads-book-send-to="AW-18065522009/P0j5CPiCv7AdENn6p6ZD"
hidden
>
<div class="ads-consent-inner">
+16
View File
@@ -170,6 +170,7 @@
id: id,
sendTo: sendTo,
trialSendTo: banner.getAttribute("data-ads-trial-send-to"),
bookSendTo: banner.getAttribute("data-ads-book-send-to"),
};
var choice = readChoice();
@@ -210,6 +211,21 @@
fireConversion(cfg.trialSendTo, action);
};
/* ---- the booking conversion: fired on a click of the booking link ---- *
* The booking happens on Google's domain, off-site, so a click is all we can observe. The
* caller does NOT preventDefault: the link opens in a new tab on its own, so even a blocked,
* slow or absent tag can never stop the booking page from opening — this only ADDS the event.
* Without consent (or the label) it fires nothing and simply runs the (optional) action.
*/
window.o4pAds.bookConversion = function (action) {
if (typeof action !== "function") action = function () {};
if (!cfg || !cfg.bookSendTo || !isGranted() || typeof window.gtag !== "function") {
action();
return;
}
fireConversion(cfg.bookSendTo, action);
};
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", init);
} else {
+14
View File
@@ -375,6 +375,20 @@
}
})();
/* ---- Booking link — fire the Google Ads booking conversion on the click, through the same
consent gate as the buy and trial conversions. The link is a plain <a target="_blank">, so
the click is never preventDefault-ed: the Google appointment page opens regardless, and a
blocked, slow or absent tag merely skips the event. Fires nothing without consent. ---- */
(function () {
var link = document.getElementById('bookingCTA');
if (!link) return;
link.addEventListener('click', function () {
if (window.o4pAds && typeof window.o4pAds.bookConversion === 'function') {
window.o4pAds.bookConversion();
}
});
})();
/* ---- Footer contact form ---- */
(function () {
var form = document.getElementById('footerContactForm');