- Network Admin (main site) → SJ FAQs → Export/Import.
- Click Import, choose the JSON file (e.g.
sj-faqs-enduser-import.json). - Review the dry-run summary — counts of new vs. updated entries.
- Click Run Import.
- If the JSON has
shhblocks, sj-help-hub auto-stamps screen context and admin visibility on each entry. - Network Admin → SJ Help Hub → Flush all caches to push entries to every subsite Help menu.
- Spot-check one subsite: Help menu shows the new entries, the contextual Help tab on each CRM screen shows the right ones.
[ADMIN] Brand and contact info reference
For all customer-facing copy, legal pages, invoices, and email signatures:
- Company: SJ Notebook
- Address: Braintree, MA, USA
- Support email:
support@sjnotebook.com - App domain:
sjcrmapp.com - Marketing domain:
sjnotebook.com
Do not put a personal email or street address in customer-facing copy.
[ADMIN] Database table prefix and key tables
Table prefix: wpp3_
Key custom tables:
wpp3_sj_crm_tenants— tenant registry (blog_id ↔ stripe_customer_id ↔ plan)wpp3_sj_journal_entries— work logwpp3_ai_task_manager_tasks— pending tasks/ideaswpp3_sj_changelog_entries— release changelogwpp3_sj_sections— section ID registry (sj-sec-XXX)
Subsite-scoped tables use prefix wpp3_{blog_id}_ per WP multisite convention.
[ADMIN] Master copies of plugins — where to edit
Always edit the master copy. Listed in project-hub/.../project-hub-manager/data/projects-map.json.
SJ CRM plugins live at: C:UsersWin11pcLocal Sitessj-crm-40apppublicwp-contentplugins
sj-crm— main CRM plugin (HOLD — do not modify)sj-crm-stripe— billingsj-crm-signup— multi-tenant signupsj-crm-health,sj-crm-items,sj-crm-rentals,sj-crm-projects— modulessj-faqs,sj-help-hub— help system
Never edit files on the live server directly — changes get overwritten on next deploy.
[ADMIN] Where are tenant subsites provisioned?
Tenant subsites are auto-created by sj-crm-stripe on successful checkout via the checkout.session.completed webhook.
Flow: Stripe Checkout → webhook fires → SJ_CRM_Stripe_Tenant_Provisioner::create_tenant_site() → wpmu_create_blog() with slug from form → sj-crm plugins activated on the new blog → admin user assigned.
Subsites live at sjcrmapp.com/{slug}/. The blog_id and stripe_customer_id are stored together in wpp3_sj_crm_tenants.
[ADMIN] How to deploy a plugin update to production
- Bump version in plugin header AND in the
VERSIONconstant. Both must match. - Update
projects-map.jsonwith new version. - Add changelog entry to plugin’s
readme.txtorCHANGELOG.md. - Run a manual DB backup (Network Admin → Tools or hosting panel).
- Zip the plugin folder — user does this, not the agent.
- Upload via SFTP or Network Admin → Plugins → Upload.
- Network Activate (or activate per-site if it’s a single-tenant module).
- Smoke-test on one subsite: load each main screen, save one record.
- Purge LiteSpeed Cache: LiteSpeed Cache → Toolbox → Purge All.
- Log in SJ Journal: what changed, version bumped, any issues.
[ADMIN] What Stripe webhook events are handled?
Six events, all in sj-crm-stripe/sj-crm-stripe.php → handle_webhook():
- checkout.session.completed — provisions tenant site
- invoice.paid — extends subscription period
- invoice.payment_failed — sends dunning email, flags account
- customer.subscription.updated — syncs plan changes
- customer.subscription.deleted — deactivates tenant (does not delete data)
- checkout.session.expired — cleans up unfinished signups
Webhook signing secret is in wp_options → sj_crm_stripe_webhook_secret.
[ADMIN] How to manually provision a tenant subsite
Use only if Stripe webhook fails or for comped accounts.
- Network Admin → Sites → Add New.
- Site Address: customer’s chosen slug.
- Site Title: business name.
- Admin Email: customer’s email.
- Save.
- Edit the new site → Plugins tab → activate sj-crm and any modules they paid for.
- Add row to
wpp3_sj_crm_tenantswith the newblog_idand Stripe customer ID (if any). - Email the customer their login link.
For comped accounts, still create a Stripe customer (no card) so future upgrades work cleanly.
[ADMIN] What’s the difference between cancelling and deactivating a tenant?
Cancelled = subscription ended, but the subsite still exists and data is retained for 30 days. User can resubscribe to reactivate.
Deactivated = tenant flag set, login blocked at the subsite, but database rows still present. Triggered automatically by customer.subscription.deleted.
Deleted = manual super-admin action. Run after the 30-day grace period for non-resubscribed accounts. Use Network Admin → Sites → Delete.
Never delete a tenant without confirming the customer is past the grace period and has been emailed.
[ADMIN] How to investigate a failed Stripe webhook
- Stripe Dashboard → Developers → Webhooks → pick the endpoint.
- Find the failed delivery (status Failed or Pending retry).
- View the response body — look for PHP error or non-200 status.
- Cross-reference with
wp-content/debug.logat the same timestamp. - Common causes: signing secret mismatch, plugin deactivated, fatal error in webhook handler, 502 from server.
- Once fixed, click Resend in Stripe to replay the event.
- Verify the side effect ran (tenant created, subscription extended, etc.).
