Skip to main content

Documentation

No results found.
Features

Project Tracking

Track client projects and jobs from kickoff to done, give the client a private live-progress link, and fire follow-up automations the moment a job is marked complete — review requests, marketing sequences, CRM logging, and webhooks.

What it does

  • Projects (Dashboard → Projects) — one record per client job: title, internal description, client (name/email/phone, optionally linked to a Client Billing client and/or CRM contact), status (in_progress / on_hold / completed / canceled), start/due dates.
  • Milestones — a checklist per project. Progress is done / total when milestones exist; otherwise a manual percent field. A completed project always reads 100%.
  • Progress updates — timestamped notes. "Visible to client" updates render on the tracking page; internal ones stay dashboard-only.
  • Client tracking page — every project gets a private tokenized URL (/project/{40-char-token}, no login) rendered in the site's full public branding: status, progress bar, milestone checklist, public update feed, and — once completed — a thank-you card with a review link (when Reviews is on).
  • Dashboard card — open-project count with an overdue subline (projects_open widget).

Starting a project from paperwork

An accepted proposal or a signed contract can open a project directly — the third leg of the agency pipeline, beside the proposal → draft-invoice conversion that already existed. The row menu on each list gains Start a project, which carries over the client (name, email, phone, the Client Billing link and the CRM contact), uses the document title, and turns its scope/body into the project's description so the tracking page opens with what was actually agreed.

It's manual by design: the operator decides when paperwork becomes live work, and a signed contract routinely precedes any work starting. The project records what it came from in a source_type/source_id morph, which makes the action idempotent — clicking twice returns the same project, and the menu item disappears once one exists.

Both lists route through the one ProjectStarter; neither module reimplements project creation.

Completion automations

Marking a project complete (the Mark Complete button, which shows exactly what will fire before you confirm) runs:

  1. CRM (when enabled): the client is upserted as a contact (source: project), the contact id is backfilled onto the project, and "Project completed: {title}" is logged on their timeline.
  2. Marketing sequence enrollment (when enabled): the client is enrolled in the project's completion sequence — per-project override, falling back to the global default (Projects → Settings). Enrollment works through the CRM contact when CRM is on, or a marketing subscriber row otherwise. Sequences enroll each person once, ever, so re-completing can't restart a drip.
  3. Automatic review request (Reviews feature): the project trigger in Reviews → Settings creates a pending review request that reviews:send-requests delivers after the configured delay, with the usual per-email cooldown and once-per-(origin, origin_id) dedupe. Leave this OFF if your completion sequence already asks for a review — otherwise the client is asked twice.
  4. Webhook: project.completed fires with id/title/client/progress/tracking URL/completed_at.

Reopen (status back to in-progress) and re-complete safely: the review request dedupes on (origin: project, origin_id) and sequence enrollment is once-per-person.

Review follow-up sequences (lives in Marketing, works without Project Tracking)

The follow-up flow deliberately lives in the Marketing feature so it can be started for any job — tracked here or not:

  • "Review follow-up" template — Marketing → Sequences → New Sequence → Start from: Template: Review follow-up. Creates a draft 3-step manual sequence: day-1 "does everything look good?" check-in, day-4 thank-you with a Leave a review button, day-8 nudge that only sends when the recipient hasn't left a review yet.
  • {{review_link}} token — usable in any campaign or sequence email (button URL or body) and SMS. At send time each recipient gets their own trackable review-funnel link (a ReviewRequest with origin: marketing, created as already-sent so the reviews sender never double-delivers it; an existing unanswered request from the last 60 days is reused so a nudge carries the same token). Click tracking never rewrites the token's href, so funnel opened_at/completed_at stay the source of truth. Requires Reviews; with Reviews off the token degrades to the site home URL.
  • Review step conditions — Only if they left a review or gave feedback / Only if they haven't left a review yet (shown when Reviews is enabled). Evaluated when the step comes due against the recipient's review requests since enrollment: rated (private feedback / first-party review) or clicked through to a platform both count as "responded".
  • Manual starts — enroll by email on the sequence edit page, from the Enroll in Sequence button on a CRM contact, or via a CRM automation rule (enroll_sequence action).

Configuration

  • Dashboard → Projects → Settings (admin): default completion sequence for new projects (each project can override with a specific sequence or "Don't enroll").
  • Dashboard → Reviews → Settings: the "After a project is completed" auto-request toggle + shared delay/cooldown.
  • Feature toggle: Settings → Features → Clients & Billing → Project Tracking (project_tracking, opt-in).

Mechanics / files

  • Module: app/Features/ProjectTracking/ — models Project (client_projects, distinct from the projects portfolio content type), ProjectMilestone, ProjectUpdate; support ProjectCompletion (completion side-effects, all fire-and-forget), ProjectStarter (proposal/contract → project) and ProjectSettings.
  • Public route project/{token} (['web', 'feature:project_tracking'], transactional — never response-cached); dashboard routes under dashboard/projects (role:manager, settings role:admin).
  • Member portal route members/projects (+ auth) → project_tracking::public.my-projects, plus the Projects pill in partials/account-nav and a card on the account dashboard. It lists the signed-in account's projects and links each one to the tokenized tracker above — the tracker stays the only place a project's detail renders. See memberships.md → The account area.
  • Cross-feature listeners live in the consuming modules (no coupling in this one): the review trigger in ReviewRequestTriggers::register() (Reviews), the webhook in WebhooksServiceProvider::registerEventHooks().
  • Marketing pieces: SequenceTemplates (template factory), ReviewLinks (Reviews-side surface minting/reading funnel links for other features), review conditions in SequenceRunner::conditionMet(), {{review_link}} substitution in SequenceRunner + SendCampaignJob + EmailRenderer::personalize().
  • Tests: ProjectTrackingTest, ProjectTrackingCompletionTest, MarketingReviewLinkTest, PipelineLinksTest (starting from paperwork).

Limitations

  • Matching a project to a signed-in account is by email (the project's client_email, or the linked invoicing client's) — a client who books under one address and signs in with another sees an empty list.
  • One flat milestone list (no phases/nesting, no per-milestone due dates).
  • Completion email content comes from the sequence you pick; there is no separate hardcoded "check-in" email.