Ops Guide

Access restricted to @scarlettstclaire.com accounts.

Ops Guide

Operations Guide

HOW-TO
GUIDE

Step-by-step workflows for every tool in the ops dashboard. Follow these guides for day-to-day publishing, commerce, and site management — and for first-time setup of new features.

COMMERCE


💰

Order Processing

requests.html

Open tool

The single console for all orders and subscriptions — from initial request through payment to fulfilment. Five stage tabs give you a clear pipeline view. Each order card shows the full history, audit trail, and all available actions for that stage.

Order status pipeline

Review Send Link Awaiting Payment To Fulfil Done

Orders with Custom Content items start in Review. Digital-only orders skip straight to Send Link. Free/£0 orders skip payment entirely and go straight to To Fulfil.

Reviewing a custom content order

1
Open Order Processing → Review tab. Custom content orders land here first. Expand the card to see each service item with Accept and Reject buttons.
2
For each item, click Accept or enter a rejection reason and click Reject. If a service item has add-ons in a hierarchy, rejecting the parent auto-rejects all its children.
3
Once all items have a decision, click Accept & Proceed to Payment (or Reject Order if everything was rejected). The total is recalculated based on accepted items. The order moves to Send Link.

Sending a payment link

1
In the Send Link tab, expand the order. Paste a payment URL (Revolut, PayPal, bank transfer, etc.) and click Send Payment Link.
2
The customer receives an email with the link and a short payment reference (e.g. SSC-7K4M) to include in their bank transfer. The order moves to Awaiting Payment with a 10-day expiry.

Confirming payment received

1
In the Awaiting Payment tab, expand the order. Enter the exact amount you received and click Confirm.
2
Exact match: payment confirmed immediately. Amount differs: you'll see two options — Send Top-up Request (emails the customer asking for the shortfall) or Confirm Anyway (records the variance and proceeds).
3
The order moves to To Fulfil.

CSV bank statement reconciliation

1
In the Awaiting Payment tab, expand any order and open the CSV Reconciliation section at the bottom of the action panel.
2
Export your bank statement as CSV and paste it into the textarea. Click Parse.
3
Each row is colour-coded: green = matched payRef + exact amount (click Confirm to process), amber = matched payRef but different amount (opens the mismatch dialog), grey = unmatched or non-GBP (skipped). Nothing is saved — re-paste fresh each session.

Fulfilling a digital product order

1
In To Fulfil, expand the order. Each line item shows its own fulfilment status and action row.
2
For digital items: paste a download URL and optionally add instructions, then click Issue to Customer ↗. The customer receives an email with the link. The link expires after 30 days (configurable in Site Config).
3
Once all items are fulfilled, the order moves automatically to Done.

Fulfilling a custom content (service) order

1
Service items in the same tree (e.g. "Standard Vid Duration + JOI Add-on") are fulfilled together. The last item in each group has a Group Fulfilment row spanning the table.
2
Click In Production ✉ to notify the customer you've started. Status changes to in_production.
3
When finished, paste the download URL and click Mark All Ready & Notify ↗. The customer receives a "content ready" email.

Putting an item on hold

1
In To Fulfil, each item row has a ghost ⏸ Hold button. Click it to enter a hold note (e.g. "out of stock — contact customer").
2
Held items show a yellow ⏸ On Hold badge and are excluded from the "all items done" check — so the order stays in To Fulfil rather than auto-completing.
3
Click Clear Hold to resume normal fulfilment for that item.

Issuing a refund

1
Expand any paid or fulfilled order in To Fulfil or Done. Click Issue Refund… at the bottom of the action panel.
2
Enter the amount, reason, and optional bank reference. The customer receives a refund notice email. The actual bank transfer must be done separately — this is record-keeping only.

Splitting an order

1
Expand any order and scroll down to the Split Order panel (available at any stage). Tick the items to split out.
2
Click Split into New Order. A new order is created for the selected items with its own payment reference. The original order's items are marked split_out.
Unpaid orders expire automatically after 10 days (configurable in Site Config → Merch & Downloads). A reminder email is sent 3 days before expiry. Expired orders appear in Done with a ↺ Revive button that resets the expiry clock.
Every action is logged in the Audit Trail section of each order card (newest first). The Email Log shows every email sent with a Resend button per row.
💳

Subscription Flow

requests.html

Open tool

Subscription requests flow through Order Processing just like orders, but skip the Review stage entirely and have a dedicated Activate step instead of per-item fulfilment.

Activating a subscription

1
Customer submits a subscription request from the showroom Members drawer → appears in Send Link tab (not Review).
2
Send a payment link as normal. Order moves to Awaiting Payment.
3
Confirm payment received → order moves to To Fulfil, showing a green "Payment confirmed" banner and an Activate Membership button.
4
Click Activate Membership. The customer's tier is updated to subscriber, a subscription record is created in Firestore, and a "Your membership is now active" email is sent. Order moves to Done.
The customer must be signed in when they submit the request — if there is no UID on the request, automatic activation will fail with an error. Ask the customer to sign in and re-submit.
👕

Merch Checkout & Dispatch

requests.html

Open tool

Merch items flow through the same Order Processing pipeline as digital products. Customers select variants (Size, Colour, etc.) and enter a shipping address at checkout. You dispatch from the To Fulfil tab.

Dispatching a merch item

1
In To Fulfil, expand the order. Merch item rows show the selected variant (e.g. Size: M) and the shipping address from the order.
2
Pack and post the item. Enter the carrier (e.g. Royal Mail) and tracking number in the item row inputs.
3
Click Mark Dispatched & Notify ↗. The customer receives a dispatch email with the carrier and tracking number. The stock count for that variant is decremented automatically in Product Manager.
If a variant sells out between order and dispatch, use the ⏸ Hold button to pause that item without blocking fulfilment of any digital items in the same order.

CATALOGUE


🎬

Product Manager

products.html

Open tool

The PIM (product information manager) for all digital SKUs. Manages titles, descriptions, pricing, tier access, content ratings, trailer/short videos, poster and thumbnail images, and Drive file links. Every save dual-writes to Google Sheets (via Apps Script) and Firestore.

Creating a new product

1
Click New Product. A blank SKU form opens with a generated ID (e.g. SKU-20260610-ABCD1234).
2
Fill in Title, Description, Price, and Tier Access (follower / subscriber / both). Set Content Rating (SFW or NSFW).
3
Add a Cover Image URL — paste a Firebase Storage or Drive download URL. This is the main product card image shown in the showroom.
4
Add Trailer URL and Short Clip URL if available. These appear on the product detail page as preview content.
5
Tick Exclusive if this product is platform-exclusive — it shows an "Exclusive" badge in the showroom and enables filtering.
6
Click Save. The product writes to Google Sheets first; if that succeeds, it writes to Firestore. Both must succeed — if AS fails, save aborts.

Adding studio assets (thumbnails & posters)

1
Open Image Studio and create your image. When exporting, choose Product Asset and select the SKU from the dropdown. This stages the image to Google Drive (not yet live).
2
Back in Product Manager, find the SKU and open the Studio Assets panel. Staged images appear here with a preview.
3
Click Activate next to the image you want to make live. This uploads from Drive to Firebase Storage and sets it as the active thumbnail or poster. The product card in the showroom updates immediately.
Dual-write requirement: Apps Script must be reachable for saves to succeed. If you see an AS error, check the AS URL in Site Config and that the deployed web app is live at the correct URL.
👕

Merch Catalogue

products.html — SKU type: Merch

Open tool

Physical merch SKUs (t-shirts, prints, accessories) are managed in Merch Catalogue (merch.html). Each SKU has variants, per-combination stock, a shipping rate, and can be set to Live (available to buy) or Register Interest (pre-launch). The entire merch section on the showroom can be toggled on/off from Site Config.

Merch-specific fields

VariantsAdd variant dimensions (e.g. Size, Colour). Enter each option on a new line. The stock grid is generated automatically from all combinations.
Stock by variantEnter available quantity per combination (e.g. S/Black: 5). Stock decrements automatically when an order is dispatched.
Shipping rate overrideOverrides the default flat shipping rate (set in Site Config) for this SKU specifically. Leave blank to use the site default.
Catalogue stateLive — available to buy. Register Interest — pre-launch; shows a "Register Interest" button instead of Add to Cart. Interest list is managed from the Register Interest panel (see below).
MOQ targetMinimum Order Quantity — the number of interest registrations needed before the item goes live. Shown as a progress bar in the interest admin panel.
Early interest discount %Percentage discount offered to early registrants if the item reaches MOQ. Applied automatically at checkout using the better-of rule (tier discount vs early interest discount).

Adding a merch item

1
In Product Manager, click New SKU. Set SKU Type to Merch — the Merch section expands below.
2
Add Variant Dimensions (e.g. Size with values S, M, L, XL). Click Add Dimension to stack multiple (e.g. Size + Colour). The stock grid regenerates as you type.
3
Fill in stock quantities per combination in the stock grid. Set a Shipping Rate Override if this item ships differently from the site default.
4
Add a Thumbnail via the Studio Assets panel — use Image Studio to export a merch thumbnail, then activate it here. Click Save SKU.

Managing a pre-launch (Register Interest) SKU

1
Set Catalogue State to Register Interest. Enter an MOQ Target (e.g. 20) and an Early Interest Discount (e.g. 15 for 15% off).
2
The showroom shows a Register Interest button on this SKU's card. Customers click it, enter their email and variant preference, and are added to the interest list.
3
Click the Register Interest ↗ toolbar button in Merch Catalogue to open the interest admin panel. See the count vs MOQ progress, variant breakdown, and export registrant emails to a text file.
4
When ready to launch, change the Catalogue State to Live and save. The showroom immediately shows Add to Cart for this SKU. Registrants who purchase will receive the early interest discount automatically (better-of vs their tier discount).
The merch section is hidden on the showroom by default. Turn it on in Site Config → Merch & Downloads → Merch catalogue enabled once your catalogue is ready.
🎨

Services Catalogue

services.html

Open tool

Manage the custom content services catalogue — the offerings that appear in the Custom Content panel on the showroom. Services are organised in a tree (categories → services → add-ons) to arbitrary depth. Customers can select a base service plus any visible add-ons.

Service types (categories)

Each service has a Service Type that groups it under a labelled category heading on the showroom. Types are defined and managed within the tool — create custom types or use defaults (Custom Video, Photo Set, Live, Audio, Other).

Adding a service

1
Click New Item. Enter a name, description, and price. Set the Service Type to place it under the correct category on the showroom.
2
To make an item an add-on to another service, set its Parent Item. Add-ons are hidden on the showroom until the parent service is selected, then revealed as expandable options.
3
Use the Copy button to duplicate a service as a starting point for a similar one. Use drag-to-reorder or the order fields to control display sequence.
4
Click Save. Changes appear on the showroom immediately — no redeploy needed.
The category filter pills on the showroom are populated from active service types. If a type has no visible services, its pill is hidden automatically.
🔄

Bulk Uploads & Updates

products-sync.html

Open tool

Scan a Drive folder to import files in bulk, sync the entire product catalogue, and backup or restore SKU data. Use this after uploading a batch of new content to Drive.

Scanning Drive to import new files

1
Upload your files to the configured Downloads Drive folder (set in Site Config → Drive Folders).
2
Open Bulk Uploads & Updates and click Scan Drive. The tool reads the folder and lists all files not yet in the catalogue.
3
Select the files you want to import and click Import Selected. Stub SKU records are created — go to Product Manager to add descriptions, pricing, and images.
The Backup function exports all SKUs to a JSON file you can save locally. Use Restore to re-import from that file if data is ever lost.

CONTENT & PUBLISHING


📢

Campaign Management Tool

announcements.html

Open tool

The main publishing tool. Create campaign posts with text, media, and hashtags, then target them to the website banner/ticker, social channels (X, Bluesky, Telegram, Instagram, TikTok, WhatsApp), or Google Calendar — immediately or on a schedule.

Post status system

Draft Ready Posted

Posts start as Draft — the channel panel is locked. Set to Ready to enable channel targeting and publishing. After posting, status becomes Posted. A Posted post can be re-opened (status: Reopened, purple) to publish to additional channels via the cross-post panel.

Creating and publishing a post

1
Click New Post. Write your post text. Add a link and hashtags if needed.
2
Attach media using the Image Optimizer panel — upload an image and it generates optimised variants per channel. For video posts, paste a Firebase Storage or Drive URL into the video field.
3
Set post status to Ready using the status bar at the top of the editor. This unlocks the channel panel.
4
In the Channels column, select your targets:
Website — set a go-live datetime for the banner/ticker to activate
Social — tick channels (X, Bluesky, Telegram, Instagram, TikTok, WhatsApp). Choose Immediate or set a scheduled datetime. WhatsApp is greyed out for NSFW posts (SFW only).
Calendar — adds an event to Google Calendar with per-channel dates
5
Optionally enable the AI Safety Check toggle (shield icon in the Social panel). When on, your post is assessed for platform policy compliance before publishing — results shown in a modal with per-platform risk cards.
6
Click Publish. Social posts go out immediately (or are queued for scheduled time). Website posts activate at the go-live time. Post IDs are stored in Firestore for each channel.

Cross-posting to additional channels

1
Find the published post in the sidebar. Open it — the status will show Posted.
2
The Cross-Post section shows all channels not yet posted to. Tick the ones you want to add. Click Publish to N channels.
3
You can also Re-open a Posted post (purple button in the channel lock overlay) to change other fields before cross-posting.

Offloading media to Drive

1
After publishing, a post with media stored in Firebase Storage shows an Offload to Drive button in the engagement panel.
2
Click it to move the files to the configured Announcements Drive folder. The original URLs update to Drive download URLs automatically — existing social posts are unaffected.
Scheduled posts are picked up by the processSocialSchedule Cloud Function every 5 minutes. There may be up to a 5-minute delay after the scheduled time before the post goes live.
Bluesky and Telegram post via their direct APIs; X, Instagram, TikTok, and WhatsApp post via Zernio. WhatsApp never posts NSFW content — it is blocked both server-side and in the UI.
🔗

Social Links & Offering Matrix

links-matrix.html

Open tool

Manages the links page at scarlettstclaire.com/links. Two types: SpicyLinks (platform links to OnlyFans, Fansly, etc.) and SocialLinks (X, Instagram, etc.). Also manages the content comparison matrix shown below the links.

Adding or editing a link

1
Click Add SpicyLink or Add SocialLink depending on the type. Fill in the platform name, URL, and display label.
2
Drag rows to reorder them — the order shown here is the order on the live page.
3
Click Save to publish. Changes go live immediately.

Editing the content matrix

1
The matrix shows what content types are available on each platform (e.g. "explicit photos", "live streams"). Edit the cells to tick or untick offerings per platform.
2
Click Save Matrix to publish. The comparison table on the links page updates immediately.
🎨

Carousel Image Manager

content.html

Open tool

Manages the homepage carousel, social feed posts, and site content. Add, reorder, and delete carousel slides. Manage the social feed shown to logged-in subscribers.

Adding a carousel slide

1
Click Add Slide. Upload or paste an image URL. Add optional caption text and a link URL if the slide should be clickable.
2
Drag the slide into position. Slides render in the order shown here.
3
Click Save. The homepage carousel updates immediately.
For best results, use Image Studio to prepare and crop carousel images before uploading here. Image Studio exports directly to the carousel format.

Image Studio

carousel-studio.html

Open tool

Browser-based image editor with three panels: import queue → canvas/crop/adjust → tray + export. Crop, adjust brightness/contrast/saturation, add text overlays (with manual positioning and rotation), and export to carousel slides, product assets, or merch thumbnails.

Editing and exporting an image

1
Import: Drag images into the import queue on the left, or click to upload. Multiple files are queued and processed one at a time.
2
Crop: Use the aspect ratio buttons (1:1, 4:5, 16:9, etc.) to set the crop. Drag the crop box to position. Click Apply Crop.
3
Adjust: Use sliders to tune brightness, contrast, saturation, and sharpness. Changes preview in real time.
4
Text overlay (optional): Type text, choose font size and colour, pick a grid position or drag to position manually, set rotation. The overlay appears as a CSS preview — it is burned into the exported image.
5
Add to Tray: Click the tray button to add the edited image to the export tray. Edit the tray name — this becomes the filename in Drive.
6
Export: Choose destination — Carousel (Firebase Storage + Firestore, shows in Carousel Manager), Product Asset (Drive staging → activate in Product Manager), or Merch Thumbnail (Firebase Storage). Click Export.
Product asset exports go to Drive staging only — they won't appear in the showroom until you click Activate in Product Manager. This prevents unfinished assets going live accidentally.
🎬

Video Studio

video-studio.html

Open tool

Browser-based video editor powered by FFmpeg.wasm — no upload to server, all processing happens locally in the browser. Trim clips, add text overlays with scrim, resize, adjust speed, and export as MP4, WebM, or GIF.

Trimming and exporting a clip

1
Load FFmpeg: On first open, FFmpeg loads automatically (20–30 seconds). A full-screen loader shows progress. Do not close the tab during this.
2
Import: Click the clip area or drag a video file in. The video loads in the preview player.
3
Trim: Drag the left handle (in-point) and right handle (out-point) on the trim bar. Click the bar to seek. The preview respects the trim range during playback.
4
Text overlay (optional): Switch to the Text tab. Type your overlay text, choose size, colour, position, and timing (start/end seconds). Enable the scrim box for better contrast.
5
Export settings: Choose format (MP4 recommended for general use, GIF for short loops), quality, and resize if needed. For social posts, MP4 at default quality works best.
6
Destination: Choose Firebase Storage (for announcement video assets) or Google Drive (for product content). Click Render & Export. Rendering is CPU-intensive and may take 30 seconds to several minutes depending on clip length.
Drive uploads are capped at ~50 MB (Apps Script limit). For larger exports, use Firebase Storage as the destination instead.
For campaign video posts to Bluesky, export to Firebase Storage under the clips/ path. The Campaign Management Tool references this path for video attachments. Bluesky accepts video up to 100 MB.

COMMUNITY


👤

Customer Management

users.html

Open tool

Analytics dashboard and tier control for all registered users. View subscribers, follower counts, revenue, and expiry forecasting. Manually change user tiers. Filter to find unverified accounts and delete them individually. Click View Full Profile → in any user drawer to open the full customer detail page.

Changing a user's tier

1
Find the user by searching by email or name. Click the row to expand their profile drawer.
2
Click Change Tier and select the new tier (anonymous / follower / subscriber). Confirm the change.
3
The user's access level changes immediately. Subscribers gain access to subscriber-tier products; followers gain free tier content.

Managing unverified accounts

1
Click the Unverified filter button in the controls row. This shows only accounts registered by email and password where the customer has not yet clicked the verification link.
2
Unverified rows are shown at reduced opacity with a ⚠ unverified label. Click Delete on any row to permanently remove the account. A confirmation prompt is shown before anything is deleted.
3
Google sign-in users are always treated as verified and never appear in this filter.
The Expiry Forecast panel shows upcoming subscription renewals and expected revenue. Use this for planning promotions around renewal windows.
IAM setup required for account deletion. Deleting accounts calls the manageCustomer Cloud Function, which needs Firebase Authentication Admin permissions. If you see a 500 error when deleting, the IAM role has not been applied yet — contact your developer. See Site Config → Operations for the fix instructions.
🗂

Customer Detail

customer-detail.html?uid=…

Full customer profile page, accessed by clicking View Full Profile → in the user drawer on Customer Management. Shows four tabs — Profile, Orders, Comments, and Support — all loaded in parallel from Firestore. A Danger Zone at the bottom allows account suspension and permanent deletion.

Profile tab

Shows Firebase UID, email, tier badge, account status, sign-in method, and Firestore metadata. Read-only.

Orders tab

All payment_requests for this customer, sorted newest-first. Shows order ID, status, total, and items.

Comments tab

All product_comments left by this customer. Shows status (pending / approved / rejected), product, and comment text.

Support tab

All support_requests linked to this customer's UID. Shows ticket type, status, and message.

Suspending an account

1
Scroll to the Danger Zone at the bottom of the page. Click Suspend Account.
2
Type the customer's name to confirm, then click Yes, Suspend. The Firebase Auth account is disabled and users/{uid}.accountStatus is set to disabled. The customer cannot sign in until re-enabled.
3
To re-enable, click Re-enable Account in the Danger Zone. All data is retained throughout.

Permanently deleting an account

1
Scroll to the Danger Zone and click Delete Account Permanently.
2
Type the customer's name to confirm, then click Yes, Delete Permanently. This batch-deletes all their product_comments and support_requests, deletes their users/{uid} Firestore doc, and deletes the Firebase Auth account.
3
Payment requests are intentionally kept as a financial audit trail. The customer's order history remains visible in Order Processing even after account deletion.
Danger Zone requires IAM setup. Suspend, re-enable, and delete all call the manageCustomer Cloud Function, which requires the Firebase Authentication Admin role on the service account. Until this is applied, all three operations return a 500 error. Contact your developer to apply the IAM fix.

Collab Requests

registrations.html

Open tool

Reviews register-interest applications from prospective co-performers submitted via collab.scarlettstclaire.com. Reject unsuitable applications or forward promising ones to your inbox for further review.

Reviewing an application

1
Open Collab Requests. Applications are listed with submission date, name, and a brief note from the applicant.
2
Click a row to read the full application. Click Forward to Inbox to email it to yourself for further consideration, or Reject to archive it.
This is a register-interest form only — no consent documents are signed here. Full model release / consent is handled separately via the Collab Site (collab.scarlettstclaire.com).
💬

Support Requests

customers.html

Open tool

View and manage support tickets, special requests, and newsletter sign-ups submitted via the site. Data is read directly from the Firestore support_requests collection — no Apps Script involved. Tickets are ordered newest-first with status and type filters.

Handling a support ticket

1
Open Support Requests. Use the Status filter (New / Open / Resolved / Closed) and Type filter (Support / Special Request / Newsletter) to narrow the list.
2
Click a ticket to expand the detail popup. The Events timeline shows the full history of status changes and admin notes for that ticket.
3
Reply to the customer directly from your email using the address shown. When resolved, use the status controls in the popup to mark it Resolved or Closed.

Deleting tickets

1
To delete a single ticket, expand it and click the inline Delete button. A confirmation prompt is shown before deletion.
2
To bulk-delete all tickets, scroll to Danger Zone at the bottom of the page. The button shows the total count before you confirm. This deletes every ticket regardless of status or type.
Newsletter sign-ups are dual-written: they appear here as type: newsletter tickets AND are forwarded to Apps Script for the mailing list. The Firestore copy is a record — the AS copy handles actual list membership.
💬

Comments Moderation

comments.html

Open tool

Approve or reject product comments and star-rated reviews submitted by subscribers. Two tabs: Comments (free-text) and Reviews (1–5 star rating + text). Both are pending by default and not visible on product pages until approved.

Moderating a comment

1
Open Comments. Pending comments appear at the top — each shows the commenter, product, date, and comment text.
2
Click Approve to make the comment visible on the product page. Click Reject to archive it without publishing.
3
To retract an already-approved comment, find it in the Approved tab and click Retract. It moves back to pending.

Moderating a review

1
Click the Reviews tab. Each review card shows the star rating, title, body, and a Verified Purchase badge if the reviewer has that SKU in their purchase history.
2
Click Approve to publish the review. Approving a Verified Purchase review immediately recalculates the average rating shown on the product/merch page.
3
To remove a published review, click Retract. The rating average is recalculated automatically. Rejected and retracted reviews are never shown to customers.
Only Verified Purchase reviews contribute to the star-rating average shown on product pages. Unverified reviews (e.g. submitted before a purchase was confirmed) are still visible after approval but are excluded from the average calculation.
⬇️

Self-Service Re-downloads

showroom/my-purchases.html (customer-facing)

Customers with a paid order can re-download their digital files without contacting support. The My Purchases page shows all paid orders and a Get download link button per digital item. No admin action required.

How it works

1
Customer goes to showroom.scarlettstclaire.com/my-purchases. All paid/fulfilled orders are listed with each digital item.
2
Clicking Get download link calls the getDownload Cloud Function, which checks the customer's purchasedSkus entitlement and returns a fresh download URL.
3
The file opens in a new tab. If the entitlement check fails (SKU not found in their history), a fallback mailto link is shown so they can contact support.
Entitlement is set automatically when you confirm payment in Order Processing. You never need to manually grant re-download access — it comes from the existing purchasedSkus index on the user's Firestore profile.

PROMOTIONS


💳

Subscription Plans

subscriptions.html

Open tool

Create and edit subscription tiers shown on the showroom. Set pricing, duration (monthly / quarterly / annual), and whether the plan recurs. Subscribers who purchase a plan appear in Customer Management.

Creating a subscription plan

1
Click New Plan. Enter a plan name (e.g. "Monthly Subscriber"), price, and duration in days.
2
Tick Recurring if this plan auto-renews. Add a short description shown to customers in the subscription drawer.
3
Click Save. The plan appears in the showroom subscription drawer immediately.
There is currently no payment processor connected. All payments are manual — customers submit a subscription request, you send a payment link, and confirm payment manually in Payment Requests.
🏷️

Discount Codes

discounts.html

Open tool

Create promotional discount codes — percentage off, fixed amount, or free access. Target specific subscription tiers or all products. Set expiry dates and maximum redemption counts.

Creating a discount code

1
Click New Code. Enter a code string (e.g. SUMMER25) — customers enter this at checkout.
2
Set the discount type: Percent (e.g. 25% off) or Fixed (e.g. £5 off). Enter the value.
3
Optionally restrict to a specific tier target (subscriber only), set an expiry date, and a max uses limit.
4
Click Save. The code is active immediately and redeemable at checkout.

SITE CONFIG


⚙️

Site Config

config.html

Open tool

Central configuration for the entire platform. Changes save to Firestore (config/public and config/backend) and take effect immediately without redeployment. All pages load config from Firestore at runtime.

First-time setup order: Identity → Legal → Operations (AS URL + password) → Drive Folders → Social Accounts → Consent & Collabs → Channels → AI Safety Check.

Identity & Legal

Brand identity fields and §2257 compliance data. Legal fields are required for the compliance statement at showroom.scarlettstclaire.com/2257.

brand_nameDisplay name used in emails and site footers.
favicon_urlURL of a hosted PNG/ICO favicon. If blank, the default SVG favicon is used.
company_nameRegistered trading/company name — shown on the §2257 compliance page.
company_numberCompanies House registration number.
custodian_nameFull legal name of the §2257 records custodian (typically your own name).
company_address_*Registered address lines, city, postcode, country — all appear on the §2257 page.
ico_numberICO (Information Commissioner's Office) registration number for UK data protection compliance.

Social Accounts

Platform handles and API credentials for all social channels. These are used by the Campaign Management Tool when publishing posts.

X (Twitter)

x_api_keyConsumer Key from developer.x.com. Used for OAuth 1.0a signing (not used for direct posting — X posts via Zernio).
x_api_key_secretConsumer Secret.
x_access_tokenAccess Token — regenerate after setting app permissions to Read & Write.
x_access_token_secretAccess Token Secret.
X credentials use OAuth 1.0a — do not use OAuth 2.0 tokens. The Access Token must be regenerated after you set app permissions to Read and Write in the developer portal.

Bluesky

bluesky_identifierYour Bluesky handle, e.g. yourname.bsky.social.
bluesky_app_passwordApp password created at bsky.app → Settings → App Passwords. Do not use your login password.

Telegram (direct Bot API)

telegram_bot_tokenBotFather token for the bot that posts to your channel. Create a bot at t.me/BotFather, add it to your channel as admin, and paste the token here.
telegram_chat_idYour Telegram channel ID — either @channelname or the numeric -100… ID. Use @userinfobot to retrieve the numeric ID.

Instagram, TikTok, WhatsApp (via Zernio)

zernio_api_keyZernio API key from your dashboard. Zernio handles posting to Instagram, TikTok, WhatsApp (and optionally X via Zernio).
zernio_account_instagram / _tiktok / _whatsappPer-platform Zernio account IDs — set in the Channels section below.
Telegram switched to direct Bot API. zernio_account_telegram is deprecated — it appears in config as "Deprecated" so you can clear it manually during the Zernio cut-over. The new credentials are telegram_bot_token and telegram_chat_id. Telegram engagement stats are unavailable via the Bot API — the UI shows "Stats unavailable" for Telegram instead of numbers.

Operations

Apps Script URL and password, commerce settings, and Google Drive folder IDs for media storage.

Apps Script

apps_script_urlThe deployed web app URL for the main Apps Script. Ends in /exec. Saved to both config/public and config/backend automatically.
apps_script_passwordADMIN_PASSWORD from Script Properties in the Apps Script project. Must match exactly.
After redeploying Apps Script (e.g. after a code change), the web app URL usually stays the same. Only update this field if the URL actually changed.

Google Drive Folders

products_folder_idDrive folder ID for product asset staging (Image Studio exports here).
downloads_folder_idDrive folder containing purchased digital files. Bulk Uploads scans this folder.
announcements_folder_idDrive folder for announcement media offloaded from Firebase Storage.

Google Calendar

google_calendar_idCalendar ID for the Campaign Management Tool calendar integration. The calendar must be shared with the Firebase service account email.

Commerce

order_notesDefault notes sent to customers with their order confirmation email.
awaiting_payment_expiry_daysDays before an awaiting-payment request auto-expires (reminder sent before expiry). Default: 7.
awaiting_payment_reminder_daysDays before expiry to send a payment reminder email. Default: 2.

Merch & Downloads

merch_catalogue_enabledSet to yes to show the Merch tab and section on the showroom. Set to no (or leave unset) to hide it. Use this while building your catalogue — flip to yes when ready.
merch_shipping_flat_rateDefault flat shipping fee (£) added to the cart total when any merch item is present. Individual SKUs can override this with their own rate in Product Manager.
download_link_expiry_daysNumber of days a customer's download link remains active after a digital order is issued. Default: 30. Customers can re-request a new link from their Purchases page after expiry.

One-time IAM setup — Customer Account Management

The suspend, re-enable, and delete operations in Customer Detail and Customer Management require the Firebase service account to have the Firebase Authentication Admin IAM role. Without it, all three operations return a 500 error. This is a one-time manual step in Google Cloud Console.

1
Go to Google Cloud Console → IAM & Admin → IAM for project scarlettstclaire-site.
2
Find the principal 276112297750-compute@developer.gserviceaccount.com (the Compute Engine default service account). Click the edit (pencil) icon.
3
Click Add another role, search for Firebase Authentication Admin, select it, and click Save. Account management operations will work immediately — no code redeploy needed.

One-time setup — Anonymous Authentication (guest orders)

Anonymous sign-in must be enabled in Firebase so guest customers can place orders without creating an account. Without it, the checkout returns auth/admin-restricted-operation and the order is not saved.

1
Open Firebase Console → scarlettstclaire-site → Authentication → Sign-in method.
2
Find Anonymous in the provider list, click it, toggle Enable on, and click Save. No code redeploy needed.

Consent & Collabs

Configuration for the collab consent pipeline — the Apps Script that processes consent submissions, the Google Sheet for records, the Drive folder for files, and the helpdesk email address.

consent_as_urlDeployed web app URL for the Consent Apps Script. Update here if you redeploy with a new URL.
consent_helpdesk_emailEmail CC'd on all consent submission confirmations.
consent_sheet_idGoogle Sheet ID where consent records are logged.
consent_sheet_nameTab name within the sheet (default: Submission_Details).
consent_drive_folder_idDrive folder where consent PDFs and ID images are stored.

Setting up the consent pipeline for the first time

1
Create a new Google Sheet and note its ID (from the URL: spreadsheets/d/ID/edit).
2
Open the Apps Script editor at script.google.com. Create a new project, paste the contents of consent_and_collabs/consent_backend.gs, and deploy as a web app (access: Anyone). Note the /exec URL.
3
Create a Drive folder for consent files and note its folder ID (from Drive URL: folders/ID).
4
Paste all IDs and URLs into the Consent & Collabs section of Site Config and click Save.

Channels

Enable or disable individual social channels in the Campaign Management Tool, and configure channel-specific details like Zernio account IDs. Six channels are pre-seeded — toggle each Active/Inactive here.

Channel summary

X (Twitter)Via Zernio. Set zernio_account_x in Social Accounts.
BlueskyDirect API (AT Protocol). Credentials in Social Accounts.
TelegramDirect Bot API. Credentials: telegram_bot_token + telegram_chat_id in Social Accounts. Engagement stats unavailable.
InstagramVia Zernio. Set zernio_account_instagram below.
TikTokVia Zernio. Set zernio_account_tiktok below.
WhatsAppVia Zernio. SFW-only — greyed for NSFW posts. Set zernio_account_whatsapp below.

Activating a channel

1
Scroll to the Channels section in Site Config. Each of the six channels has an Active toggle.
2
For Zernio channels (Instagram, TikTok, WhatsApp): paste the Zernio account ID into the field. Find it in your Zernio dashboard → Connected Accounts.
3
Toggle the channel Active and click Save. Active channels appear in the Campaign Management Tool channel panel immediately.
WhatsApp is SFW-only. The server always skips WhatsApp when a post's content rating is NSFW — even if the channel is selected. The UI also greys it out proactively. No action needed; the guard is automatic.

AI Safety Check

Optional Gemini AI integration that assesses post content against 2026 platform policies before publishing. When a Gemini API key is configured, posts are checked automatically (if the toggle is on). Without a key, a copy-paste fallback prompt is shown instead.

gemini_api_keyGoogle AI Studio API key (starts with AIza…). Free tier: 1,500 requests/day — no credit card required.

Getting a free Gemini API key

1
Go to aistudio.google.com/apikey and sign in with your Google Workspace account.
2
Click Create API key. Select an existing Google Cloud project or create a new one.
3
Copy the key (starts with AIza…) and paste it into the AI Safety Check section of Site Config. Click Save.
4
In the Campaign Management Tool, enable the AI safety check toggle (shield icon in the Social channels panel) before publishing to activate it.
The AI check assesses each post against per-platform 2026 policy summaries and returns risk levels: Safe (green), Caution (amber), High Risk (orange), or Do Not Post (red). You can override the assessment and proceed, or cancel and edit the post. The toggle is opt-in and off by default.
X / ACC enrolment: The AI prompt treats your X account as ACC-enrolled for assessment purposes. Complete actual enrolment at developer.x.com (requires government ID, age verification, and a clean 180-day account history) to stay compliant.