Pivot from the hedge/second-entity framing to the consolidation pitch: one CRTC carrier as the home base, nexus in Canada, customers onboarded from anywhere. Lead value props with the three concrete reseller realities: - No FCC reporting (no 499-A/Q, no RMD recert) - No USAC/USF on your revenue (contribution sits upstream) - No STIR/SHAKEN to set up or run (reseller can't get a US token; upstream signs) Add: No FCC Section 214 / no ongoing 214 burden -- CRTC BITS is a cheap, low-burden notification by comparison. Header/subject reworked; keeps the honest US-termination + upstream-signing explanation.
160 lines
12 KiB
Python
160 lines
12 KiB
Python
#!/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 (
|
|
'<table width="100%" cellpadding="0" cellspacing="0" border="0" style="margin:8px 0 24px;"><tr>'
|
|
'<td style="background:#0f7a3d;border-radius:8px;padding:18px 24px;text-align:center;">'
|
|
'<p style="margin:0 0 4px;font-family:Arial,sans-serif;font-size:13px;color:#bdf0cf;letter-spacing:1px;text-transform:uppercase;font-weight:600;">Limited-time offer</p>'
|
|
f'<p style="margin:0 0 6px;font-family:Arial,sans-serif;font-size:22px;font-weight:800;color:#ffffff;line-height:1.2;">$200 off your Canadian carrier setup</p>'
|
|
f'<p style="margin:0;font-family:Arial,sans-serif;font-size:14px;color:#d6f5e1;">Use code <span style="font-family:\'Courier New\',monospace;font-weight:700;color:#ffffff;background:rgba(255,255,255,0.18);padding:2px 8px;border-radius:4px;">{CODE}</span> at checkout · expires <strong style="color:#ffffff;">Friday at 11:59pm ET</strong></p>'
|
|
'</td></tr></table>'
|
|
)
|
|
|
|
|
|
def guide_block():
|
|
"""PDF lead-magnet download block (Listmonk can't attach files)."""
|
|
return (
|
|
'<table width="100%" cellpadding="0" cellspacing="0" border="0" style="margin:24px 0;"><tr>'
|
|
'<td style="background:#f0f4ff;border:1px solid #dde5f0;border-radius:8px;padding:20px 24px;">'
|
|
'<table cellpadding="0" cellspacing="0" border="0"><tr>'
|
|
'<td style="vertical-align:middle;padding-right:16px;font-size:34px;line-height:1;">📄</td>'
|
|
'<td style="vertical-align:middle;">'
|
|
'<p style="margin:0 0 4px;font-family:Arial,sans-serif;font-size:15px;font-weight:700;color:#1a2744;">Free guide: Canadian Wholesale Carrier & Vendor Reference</p>'
|
|
'<p style="margin:0 0 10px;font-family:Arial,sans-serif;font-size:13px;color:#4a5568;line-height:1.6;">12 vetted Canadian wholesale partners for voice termination, SIP trunking, UCaaS, and <strong>both US and Canadian DIDs</strong> — the upstream vendors you’ll work with once your Canadian carrier is live, and which of them can provision US numbers.</p>'
|
|
f'<a href="{GUIDE_URL}" style="display:inline-block;font-family:Arial,sans-serif;font-size:14px;font-weight:700;color:#1e40af;text-decoration:none;">Download the PDF →</a>'
|
|
'</td></tr></table>'
|
|
'</td></tr></table>'
|
|
)
|
|
|
|
|
|
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 <strong>Q3 2026 USF contribution factor at 38.8%</strong> — up from 37.0% in Q2, and effective July 1. That is the rate US carriers remit on the interstate and international end-user revenue they report on the 499.")
|
|
+ stats(
|
|
("38.8%", "Q3 2026 USF<br>contribution factor"),
|
|
("+1.8 pts", "increase over<br>Q2 (37.0%)"),
|
|
("Jul 1", "effective date<br>(FCC DA-26-546A1)"),
|
|
)
|
|
+ P("38.8% is near the highest the factor has ever been — a decade ago it sat in the mid-teens. And USF is just one line on a long list. Here is the full load a US-registered voice provider carries today:")
|
|
+ UL(
|
|
"<strong>USF contributions</strong> — 38.8% of interstate/international end-user revenue, filed and remitted to USAC via the 499",
|
|
"<strong>FCC Form 499-A / 499-Q</strong> — annual and quarterly revenue filings, with true-ups and audit exposure",
|
|
"<strong>Robocall Mitigation Database</strong> — annual recertification; miss it and your traffic gets blocked",
|
|
"<strong>STIR/SHAKEN</strong> — standing up and running your own call-authentication / signing posture",
|
|
"<strong>Photo-ID “Know Your Customer” rules</strong> — under the FCC’s 2025 Robocall Mitigation Order, collecting and authenticating a government-issued photo ID for every new customer before you turn up service",
|
|
"<strong>CALEA</strong> — lawful-intercept capability and SSI filing",
|
|
"<strong>Section 214 + Team Telecom, state PUC registrations, FCC regulatory fees</strong> — on top of all of the above",
|
|
)
|
|
+ H2("The idea: run your whole VoIP business as a Canadian carrier.")
|
|
+ P("Not a side entity or a backup — your actual home base. You set up one CRTC-registered Canadian carrier, put your customers on it <strong>from anywhere</strong> (US, Canada, or international), and your nexus — the carrier of record, your billing, banking, contracts, and regulatory home — sits in Canada.")
|
|
+ bq("As a Canadian reseller you don’t report to the FCC, you don’t tax your customers for USAC, and there is no STIR/SHAKEN program for you to build and operate. Those obligations live with the upstream wholesale carriers you buy from — not with you.")
|
|
+ H2("What that means in practice.")
|
|
+ UL(
|
|
"<strong>No FCC reporting.</strong> A Canadian reseller that isn’t an FCC-registered carrier has nothing to file with the FCC — no 499-A, no 499-Q, no RMD recertification",
|
|
"<strong>No USAC/USF on your revenue.</strong> You don’t register with USAC or remit the 38.8% contribution — that obligation sits upstream, not on your customer billing",
|
|
"<strong>No STIR/SHAKEN to set up or run.</strong> A reseller can’t even be issued a US signing token — the upstream carrier that owns the numbers signs the calls. There is no authentication program for you to stand up, certify, or maintain",
|
|
"<strong>No FCC photo-ID mandate</strong> and <strong>no CALEA build-out</strong> in the US sense for your Canadian entity",
|
|
"<strong>No FCC Section 214, no ongoing 214 burden.</strong> Where the FCC requires an international Section 214 authorization (with Team Telecom review and continuing obligations), the CRTC equivalent — a BITS registration — is a simple, low-cost notification with no ongoing 214-style burden",
|
|
"<strong>Customers from anywhere.</strong> Onboard US, Canadian, or international customers onto one Canadian carrier — same +1 dialing, nothing changes on their end",
|
|
"<strong>US numbers still work.</strong> Several Canadian wholesale carriers provision <strong>US DIDs</strong> to CRTC-registered carriers, so you can serve US customers directly — the free guide below lists which ones",
|
|
"<strong>One clean jurisdiction.</strong> Your carrier of record, banking, and contracts all sit in Canada — outside the FCC’s reach",
|
|
)
|
|
+ H2("“How do I terminate to the US then?”")
|
|
+ P("Routinely. Many US-based long-distance termination operators and wholesale carriers actively accept traffic from Canadian carriers — cross-border voice is one of the most common interconnects there is. You buy US numbers and US termination from a wholesale partner, and they handle the US-side STIR/SHAKEN signing on the way out — exactly how the vast majority of small carriers already rely on an upstream provider to sign for them. Your Canadian-origin traffic falls under the CRTC’s lighter regime, handled by your Canadian trunking provider.")
|
|
+ P("The point: the heavy US compliance stack — USF, the 499s, the RMD, photo-ID KYC, the signing certificates — rides on the upstream wholesale carriers, not on your day-to-day operation.")
|
|
+ H2("What we set up — turnkey, in 6–10 weeks.")
|
|
+ UL(
|
|
"Incorporation in <strong>British Columbia or Ontario</strong> — your Canadian carrier entity",
|
|
"<strong>CRTC registration</strong> (domestic reseller + BITS international authorization)",
|
|
"Canadian DID provisioned under your new carrier identity",
|
|
"Virtual registered office, <strong>.ca domain</strong> + up to 14 email addresses",
|
|
"Full corporate binder, delivered digitally — plus a Canadian business-banking referral",
|
|
)
|
|
+ coupon_banner()
|
|
+ cta("Start your Canadian carrier setup — $200 off →", ORDER_URL)
|
|
+ guide_block()
|
|
+ PS(f"Questions about moving your VoIP onto a Canadian carrier? {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% \u2014 run your VoIP as a Canadian carrier instead ($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%.<br>Run your VoIP as a Canadian carrier.",
|
|
"One CRTC carrier, nexus in Canada, customers from anywhere",
|
|
),
|
|
flagbar(
|
|
"US carrier \u2014 38.8% USF + the full FCC stack",
|
|
"Canadian carrier \u2014 no FCC reporting, no USAC, no S/S to run",
|
|
),
|
|
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())
|