#!/usr/bin/env python3 """ create_crtc_usf_campaign.py — One-off CRTC marketing email hooked on the Q3 2026 USF contribution-factor increase. Audience : Listmonk list 3 (FCC Carriers - Direct Contacts, ~6,046 enabled). Hook : Q3 2026 federal USF contribution factor = 38.8% (up from 37.0% in Q2), effective Jul 1 (FCC PN DA-26-546A1). Offer : $200 off the CRTC carrier package service fee with code CANADA200, valid through Fri Jun 19 2026 23:59 ET. The CRTC order page auto-applies ?code= from the URL, so the CTA links carry it. Lead : "Canadian Wholesale Carrier & Vendor Reference Guide" PDF, hosted at magnet performancewest.net/guides/canada-carrier-guide.pdf (Listmonk campaigns can't attach files, so we link a prominent download). Creates the campaign in Listmonk as a DRAFT. Sending is a separate, manual, STOP-and-confirm step in the Listmonk UI (or set status via API). Run: python3 scripts/workers/create_crtc_usf_campaign.py # draft on list 3 python3 scripts/workers/create_crtc_usf_campaign.py --test # draft to a test list/email """ import argparse import os import sys # Make `scripts` importable whether run from repo root or scripts/workers. _REPO = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) if _REPO not in sys.path: sys.path.insert(0, _REPO) from scripts._email_plaintext import html_to_text # noqa: E402 from scripts.workers.campaign_helpers import ( # noqa: E402 CONTACT, P, PS, H2, UL, bq, cta, hdr, flagbar, stats, assemble, ftr, create_campaign, ) LIST_ID = 3 CODE = "CANADA200" GUIDE_URL = "https://performancewest.net/guides/canada-carrier-guide.pdf" ORDER_URL = f"https://performancewest.net/order/canada-crtc?code={CODE}" def coupon_banner(): """Prominent $200-off banner with expiry.""" return ( '' '
' '

Limited-time offer

' f'

$200 off your Canadian carrier setup

' f'

Use code {CODE} at checkout  ·  expires Friday at 11:59pm ET

' '
' ) def guide_block(): """PDF lead-magnet download block (Listmonk can't attach files).""" return ( '' '
' '' '' '
📄' '

Free guide: Canadian Wholesale Carrier & Vendor Reference

' '

12 vetted Canadian wholesale partners for voice termination, DIDs, SIP trunking and UCaaS — the upstream vendors you’ll work with once your Canadian carrier is live.

' f'Download the PDF →' '
' '
' ) def build_body(): return ( P("Hi {{ .Subscriber.FirstName }},") + P("If you contribute to the federal Universal Service Fund, your Q3 number just went up again.") + bq("The FCC has set the Q3 2026 USF contribution factor at 38.8% — up from 37.0% in Q2, and effective July 1. That is the rate you remit on the interstate and international end-user revenue you report on your 499.") + P("38.8% is near the highest the factor has ever been. A decade ago it sat in the mid-teens. For a small or mid-size US carrier, that is a steadily rising tax on every interstate dollar you bill — on top of everything else the FCC requires.") + stats( ("38.8%", "Q3 2026 USF
contribution factor"), ("+1.8 pts", "increase over
Q2 (37.0%)"), ("Jul 1", "effective date
(FCC DA-26-546A1)"), ) + H2("The US carrier burden, in one place.") + P("USF is just the line item that moved this quarter. The full load a registered US carrier carries:") + UL( "USF contributions — now 38.8% of interstate/international end-user revenue, filed and remitted via the 499", "Photo-ID “Know Your Customer” rules — under the FCC’s 2025 Robocall Mitigation Order, you must collect and authenticate a government-issued photo ID for every new customer before you can turn up their phone service", "FCC Form 499-A / 499-Q — annual and quarterly revenue filings, with true-ups and audit exposure", "Robocall Mitigation Database — annual recertification; miss it and your traffic gets blocked", "STIR/SHAKEN — call-authentication implementation and ongoing attestation", "CALEA — lawful-intercept capability, SSI filing, and the cost of a compliant solution", "Section 214 + Team Telecom — for international service, with national-security review that can stall financings and M&A", "State PUC registrations and FCC regulatory fees on top of the federal load", ) + H2("Why smaller carriers are standing up a Canadian operation.") + P("A CRTC-registered Canadian carrier is a separate legal entity in a separate regulatory jurisdiction. For the voice traffic you move there, the US compliance stack simply does not apply:") + UL( "No USF. Canada funds its contribution program differently — there is no 38.8% factor on your Canadian carrier’s revenue", "No Robocall Mitigation Database recert and no FCC 499 for the Canadian entity", "No FCC photo-ID mandate. The FCC’s government-ID “Know Your Customer” rule does not apply to your Canadian carrier’s customers", "No CALEA mandate in the US sense — lawful-intercept obligations are far lighter and cheaper", "No Section 214 / Team Telecom — CRTC registration is a notification, not an application with a national-security review", "Same +1 country code. Your customers dial exactly the same way — nothing changes on their end", "A clean second jurisdiction — an FCC enforcement action against your US entity does not reach a Canadian corporation", ) + bq("You do not give up your US business. You add a Canadian carrier alongside it — for the voice traffic that doesn’t need to sit under the FCC, and for the Canadian market you can now sell into.") + H2("What we set up — turnkey, in 6–10 weeks.") + UL( "Incorporation in British Columbia or Ontario — a separate legal entity from your US company", "CRTC registration (domestic reseller + BITS international authorization)", "Canadian DID provisioned under your new carrier identity", "Virtual registered office, .ca domain + up to 14 email addresses", "Full corporate binder, delivered digitally — plus a Canadian business-banking referral", ) + coupon_banner() + cta(f"Start your Canadian carrier setup — $200 off →", ORDER_URL) + guide_block() + PS(f"Questions about how the Canadian structure would work for your traffic? {CONTACT}. The {CODE} discount is good through Friday at 11:59pm ET.") + P("— Performance West") ) def main(): ap = argparse.ArgumentParser() ap.add_argument("--test", action="store_true", help="create against a test list id (env CRTC_TEST_LIST) instead of list 3") ap.add_argument("--name", default="CRTC USF Q3 \u2014 38.8% increase + $200 off (CANADA200)") ap.add_argument("--subject", default="USF jumps to 38.8% in Q3 \u2014 here\u2019s the Canadian alternative ($200 off)") args = ap.parse_args() lists = [int(os.getenv("CRTC_TEST_LIST", "0"))] if args.test else [LIST_ID] if args.test and lists == [0]: print("--test requires CRTC_TEST_LIST env var (a test list id)", file=sys.stderr) return 1 body = assemble( hdr( "USF Increase \u2014 Q3 2026", "USF just hit 38.8%.
There’s a Canadian alternative.", "The federal contribution factor rose again, effective July 1", ), flagbar( "US carrier \u2014 38.8% USF + the full FCC stack", "Canadian CRTC carrier \u2014 no USF, separate jurisdiction", ), build_body(), ftr(""), ) altbody = html_to_text(body) print(f"=== Creating CRTC USF campaign (list {lists}) ===") cid = create_campaign(args.name, args.subject, lists, body, altbody=altbody, status="draft") if cid: print(f"\nDraft created (id {cid}). Review/preview in Listmonk, then send manually.") print(f"Body: {len(body):,} chars HTML / {len(altbody):,} chars plaintext") return 0 if cid else 1 if __name__ == "__main__": raise SystemExit(main())