Commit graph

27 commits

Author SHA1 Message Date
justin
618fafe1d5 order: payment-first express checkout + fix dead Tawk chat widget
Conversion fix for the checkout drop-off (54 sessions reached an /order/ page
over 3 days, 0 advanced to payment). Root cause was friction, not a bug: every
order page dropped a cold email-click straight into a 28-field intake Wizard
before showing any payment option.

- New ExpressCheckout.astro: payment-first entry. Shows price + the minimal
  fields the API needs (prefilled from public records: ?dot= FMCSA census for
  trucking, ?npi= NPPES lookup for healthcare) + Continue to payment. Creates a
  single-service batch-of-one (POST /compliance-orders/batch, which does NOT
  gate Stripe on intake_data_validated) then create-session -> Stripe. Full
  intake is collected AFTER payment via the per-service 'Complete Your Intake
  Form' email the webhook already sends (links to /order/<slug>?order=CO-xxx,
  which re-enters the Wizard in paid-intake mode).

- New OrderFlow.astro: single source of truth replacing ~50 near-identical thin
  Wizard wrappers. Trucking + healthcare default to payment-first (express on
  top, marketing hero moved BELOW the CTA). Telecom + corporate keep Wizard-first
  (rich pre-payment FCC/499 intake, no public-records prefill). Paid-intake
  re-entry (?order=/?token=) always renders the full Wizard.

- Rewrote all 50 /order/*.astro pages to use OrderFlow (foreign-qualification
  keeps its multi-state toggle via slotted content).

- Fixed the dead Tawk.to live-chat widget site-wide: the snippet set an invalid
  crossorigin='*' attribute, forcing the browser into anonymous CORS mode and
  blocking the script (0 chat requests fired anywhere). Removed it to match
  Tawk's official snippet (footer partial + 73 static public/*.html files).

Verified: build clean; express on top with hero below; ?dot=/?npi= prefill;
paid-intake re-entry swaps to Wizard; telecom stays wizard-first; batch-of-one
-> live Stripe URL; both POST endpoints allow the prod origin via CORS.
2026-06-25 11:32:48 -05:00
justin
f481a1d13c analytics: filter email-scanner / headless traffic out of Umami stats
Email security gateways (Microsoft Defender Safe Links / ATP, Proofpoint,
Mimecast, Barracuda, etc.) auto-fetch and often render every link in a
campaign email to scan for malware. The advanced ones drive a real headless
browser, execute JS, and fire Umami pageviews/clicks that masquerade as human
visits -- inflating campaign click-through.

New site/public/js/pw-bot-filter.js queries multiple real-browser signals and
gates Umami via its official data-before-send hook (umamiBeforeSend), dropping
all events when the visitor is a bot. Signals (from empirical chromium probing):
  decisive: navigator.webdriver, HeadlessChrome UA, known scanner UAs, zero/
            collapsed screen|viewport|outer geometry, window LARGER than the
            physical screen (impossible on real HW; uses outerW/H so page zoom
            does not false-positive), software GPU rasterizer (SwiftShader/
            llvmpipe/swrast via WebGL UNMASKED_RENDERER), zero logical CPUs.
  soft (>=2 to trip): tiny screen, inner>screen, low color depth, empty
            navigator.languages, no input device (no fine/coarse pointer + no
            hover + 0 touch), no WebGL on a desktop UA.
Designed to FAIL OPEN: only strong/corroborated evidence suppresses, so real
visitors (incl. zoomed, privacy-tooled, remote-desktop, kiosk) still count.

Wired before the Umami tag in Base.astro (Astro pages) and all 86 static
public/**/*.html pages; both load with defer so order is guaranteed and the
hook is defined before Umami reads it.

Tested end-to-end with chromium (site/tests/bot-filter.test.sh, 4/4):
default headless-new, spoofed-Windows-UA + normal 1366x768 window, and
spoofed-UA + 1x1 window are all caught; hook returns null to drop the event.
2026-06-18 02:02:34 -05:00
justin
b5b2e6e6c3 site: add DEXIT corporate-services page + readiness assessment + cited filings
New page /services/corporate/dexit-reincorporation (matches CRTC service-page
structure): explains DEXIT, the DE franchise-tax dollar driver (real Oracle Health
proxy: $23,600 -> ~$1,000), NV/TX/FL destination guidance, 6-step how-it-works,
3 cited real SEC reincorporation filings (Oracle Health, FG Financial, LogicMark)
with verbatim quotes + EDGAR links, honesty callout, and a lead-gen CTA ('Get my
DEXIT estimate' -> /contact?topic=dexit, NOT a buy-now checkout). Linked from the
corporate services index (new card) + the global Services dropdown across the site.

docs/dexit-cited-filings.md: the filing excerpts + verified gov/statute links.
docs/dexit-readiness-assessment.md: HONEST e2e readiness -- new NV/TX formation is
built (checkout order_type=formation -> formation_orders -> ERPNext SO ->
formation_worker -> TX/NV adapters) but unverified e2e; the 'move a company'
(conversion/domestication) flow + corporate annual-report automation are NOT built;
EIN is kept on a conversion (our ein_worker does NEW EINs only). Page stays lead-gen
until the generic entity-conversion SKU + admin-assisted handler are built+tested.
2026-06-09 07:35:12 -05:00
justin
0a40e4874e fix(site): bug audit fixes - dot-compliance cart prices now match SERVICE_META (12); /pricing/bundles wrong category links (4); fcc tool order CTAs (new-carrier->fcc-carrier-registration, canada-crtc); reset-password logo; nav duplicate id (137 pages via sync_nav); +3 DOT services in SERVICE_META; classification IntakeStep type 2026-06-06 22:29:38 -05:00
justin
7399211271 trust/security: DMARC p=reject; MTA-STS cert+HTTPS policy live; cookie consent banner (CSP-safe); /accessibility page; footer legal links (Security/Accessibility) on all pages; scope TrustedSite to /order payment pages only 2026-06-06 21:01:36 -05:00
justin
bd9a70607f fix: maintain Services dropdown header from one canonical source
The site header / Services mega-dropdown was duplicated across two render
systems (Astro pages via Base.astro->nav.html, and ~80 pre-rendered static
public/**/index.html pages each embedding their own copy). They had drifted
into 5 different variants (missing 'New Carrier Setup', misplaced Healthcare
column, NEW vs FREE badges, em-dash encoding differences), so
dev.performancewest.net, the order pages, and the rest of the site disagreed.

- Make site/src/partials/nav.html the single source of truth (adopts the most
  complete variant).
- Add scripts/sync_nav.py to rewrite every static page's <nav> block from
  nav.html (idempotent; --check guards against drift in CI/deploy).
- Run the sync automatically in deploy.sh and scripts/deploy-dev.sh.
- Deprecate scripts/inject_healthcare_nav.py (now delegates to sync_nav.py).
- Neutralize the broken no-op SiteNav.astro component.

All 80 headers + the Astro-built order pages now render the identical dropdown.
2026-06-05 14:27:24 -05:00
justin
5cfe9702e2 Add Healthcare/NPI section to nav dropdown across all static pages
The site's pre-rendered public/**/index.html pages each embed their own copy
of the Services mega-dropdown and do not read src/partials/nav.html, so the
earlier nav.html-only edit never appeared. inject_healthcare_nav.py adds the
canonical Healthcare block (Medicare Revalidation, Medicare Enrollment, NPI/
NPPES Services, free NPI Compliance Check) to the desktop Column 3 + mobile
menu of all 80 static pages. Idempotent.
2026-06-05 03:05:19 -05:00
justin
3d611e97a4 tawk mobile UX: hide widget on small screens to stop text overlay popups
Adds Tawk_API.onLoad mobile guard (max-width 768px -> hideWidget) in shared
footer snippet and current built pages so mobile browsers no longer get the
proactive text bubble covering content.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 12:31:01 -05:00
justin
21b94c9ea9 add New Carrier Setup link to nav across all static pages
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-30 22:12:23 -05:00
justin
3a197f591f Sync nav/footer across all 62 static HTML pages
Bulk updated nav to include Trucking/DOT section in desktop dropdown,
mobile menu, and footer across all public/ HTML pages. Consistent
site chrome everywhere now.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-29 16:31:03 -05:00
justin
4c023b85d1 Change 'Discount code' to 'Referral code' on order pages
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-28 23:59:54 -05:00
justin
bf0c6dc85e Hide payment methods when order total is $0
When discount brings total to zero, hide the payment method selector
and change button from "Continue to Secure Payment" to "Place Free Order".

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-22 01:32:30 -05:00
justin
a8cdfc65f6 Fix: promo re-render trigger used wrong checkbox selector
Was looking for .svc-cb:checked but checkboxes use
input[data-slug]:checked. Discount display never updated after
promo info loaded.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-22 01:30:26 -05:00
justin
b81e102d39 Validate allowed_emails on discount code lookup
The /api/v1/discount/:code endpoint now checks allowed_emails when
an email is provided. If the email isn't in the allowed list, returns
valid:false so the frontend doesn't show a fake discount. The promo
field is cleared and unlocked if validation fails.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-22 01:08:51 -05:00
justin
ae5dc4745e Fix: fetch actual discount type/value from API instead of hardcoding 25%
The checkout page was hardcoding 25% for all promo codes. Now fetches
/api/v1/discount/:code to get real discount_type (percent vs flat) and
discount_value, then displays correct amount.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-22 00:56:44 -05:00
justin
fdbed5c097 Pre-fill email from URL on checkout and compliance checker
Email passes through the full funnel: campaign email (?email=) →
compliance checker → order page. Reduces friction for campaign
recipients who would otherwise have to type their email manually.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-22 00:49:28 -05:00
justin
d39e10485f Add URL promo code pre-fill and fix discount stacking logic
- Checkout page reads ?code= or ?promo= from URL, pre-fills and locks the
  promo field, shows the promo discount in the summary instead of the 15%
  bundle discount
- API: when a promo code % >= bundle %, replace the bundle discount entirely
  instead of stacking (e.g. MEMORIAL25 at 25% replaces the 15% bundle)
- Also checks discount code expiration in the query

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-21 15:06:19 -05:00
justin
45e2172417 Fix checkout page UX: card first, shorter legal, trust signals, help link
- Card payment now default (was ACH — lower trust barrier for new customers)
- Removed +3% surcharge labels (reduces friction)
- Shortened authorization text to one line (was intimidating paragraph)
- Added trust signals below button: 256-bit SSL, Powered by Stripe, PCI compliant
- Added "Questions?" help box with phone + email below checkout
- Button text: "Continue to Secure Payment" with green glow shadow

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-18 20:57:06 -05:00
justin
fa80c6dab9 Add FCC penalty warnings below order total on checkout page
Shows specific penalty amounts for each filing type:
- RMD: $500K per violation, network disconnection
- CPNI: $239K per violation, $2.39M continuing
- 499-A: USAC Red Light blocks all FCC applications
- CALEA: $10K/day court-enforced
- Registration forfeiture for persistent non-compliance

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-09 11:11:26 -05:00
justin
bd5193e45f Add Umami custom event tracking across all key pages
- Created /js/pw-analytics.js with conversion funnel events
- Added to Base.astro layout (all Astro pages) + 6 static HTML pages
- Events tracked: compliance-check-start, compliance-check-complete,
  order-cta-click, checkout-page-view, checkout-start, esign-opened,
  esign-submitted, campaign-click (UTM attribution), contact-form-submit
- Server-side payment-complete event from checkout webhook via Umami API
- Auto-tracks any element with data-track="event-name" attribute

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-05 05:10:13 -05:00
justin
7d783bdb39 Reprice services: à la carte ~$2,000 vs FCC Carrier Reg bundle $1,299
Individual services repriced so buying separately costs ~$2K, making
the $1,299 FCC Carrier Registration a clear 35% savings:

- CORES/FRN: $99 → $149
- Form 499 Initial: $299 → $349
- D.C. Registered Agent: $99 → $149/yr
- RMD: $219 → $249 (+ $100 FCC fee)
- CPNI: $149 → $199
- CALEA SSI: $299 → $799 (includes consulting work)
- BDC Broadband: $199 → $249
- BDC Voice: $149 → $199
- BDC Both: $299 → $349

Retired New Carrier Bundle ($1,799) — redirected to FCC Carrier
Registration ($1,299) which includes more services and the wizard.

Updated prices in: API catalog, batch order page, compliance checker CTA.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-04 06:23:19 -05:00
justin
5e74c1dcb9 Split discontinuance CTA into two options based on revenue
When user selects "cancel registration" in the compliance checker:
- Option 1: "499-A Discontinuance (incl. zero-revenue filing)" $299
  For carriers with no revenue — includes final zero-revenue 499-A
  + deactivation letter + CORES update
- Option 2: "499-A Filing + Discontinuance" $798 ($499+$299)
  For carriers with actual revenue — full 499-A filed separately
  + deactivation process

Standalone discontinuance ($299) is for carriers already current
on filings who just want to close out.

Handler detects whether zero-revenue filing is included vs
handled by a separate full 499-A order.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-03 03:39:52 -05:00
justin
0fc318cb38 Add 499-Q intake page, 499-Q handler, and 499-A discontinuance handler
499-Q Quarterly Filing:
- Intake page at /order/fcc-499q with simplified revenue form
  (4 fields: carrier's carrier inter/intra, end-user inter/intra)
- Zero-revenue confirmation checkbox
- Handler creates admin todo with filing details + sends client email
- Registers as fcc-499q in SERVICE_HANDLERS

499-A Discontinuance:
- Handler creates admin todo with step-by-step USAC instructions
  (file zero-revenue 499-A, request account closure, confirm CPNI/RMD)
- Sends client confirmation email explaining the process
- Compliance checker CTA: when user selects "No — cancel registration"
  in the 499-A toggle, shows discontinuance option ($299) instead of
  standard filing
- Order page maps form_499a_disc to fcc-499a-discontinuance slug

Compliance checker intelligence:
- 499-A toggle tracks _499aVariant (null/zero/discontinuance)
- CTA adapts: revenue=standard 499-A, zero=zero-revenue, cancel=discontinuance
- Reset clears variant flag

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-03 02:34:18 -05:00
justin
3e04a8fc16 Add zero-revenue 499-A filing at $179
New service slug fcc-499a-zero for carriers with no telecom revenue:
- $179 instead of $499 (no revenue analysis needed)
- Minimal intake: entity, officer, filer ID, filing type only
- Skips revenue schedules (blocks 3-4), USF calculations (block 5),
  traffic study upload, and revenue workbook generation
- Fills blocks 1-2 and 6 only, all revenue lines left as zero

Compliance checker: shows both options (mutually exclusive checkboxes)
Order page: maps form_499a_zero to fcc-499a-zero slug
Handler: detects slug and skips revenue pipeline
DC Agent shown when either 499-A variant is checked

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-03 02:04:18 -05:00
justin
118d24cc1a Rename 'IPES & ISP Registrations' to 'FCC Carrier / ISP Registration'
Updated across 61 static HTML files (nav links), bundles catalog,
service page title/description/heading, and llms.txt.
URL stays /services/telecom/ipes-isp (no redirect needed).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-29 08:06:47 -05:00
justin
cbfb8d6091 Add engagement authorization, remove price headers from intake pages, fix duplicate emails
- Add clickwrap authorization checkbox to fcc-compliance, state-puc, neca-ocn order pages
- Store engagement_accepted_at/ip/version in compliance_orders (migration 074)
- Add 499-A past-due/multi-year eSign engagement letter generator
- Gate 499-A handler on engagement signature for past-due/multi-year orders
- Remove price/tax/fee headers from all 19 intake pages (post-payment only)
- Fix duplicate confirmation email for compliance_batch orders
- Add USAC past-due fee negotiation research doc

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-28 02:50:02 -05:00
justin
f8cd37ac8c Initial commit — Performance West telecom compliance platform
Includes: API (Express/TypeScript), Astro site, Python workers,
document generators, FCC compliance tools, Canada CRTC formation,
Ansible infrastructure, and deployment scripts.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-27 06:54:22 -05:00