What it does
YouTube never reports description-link clicks. You can see that a video got 40,000 views, but not that it produced eleven clicks, three leads and one closed deal — so the video that actually pays for the channel is invisible in YouTube Studio.
VidWorth closes that loop by owning the middle of it:
- Views come from the YouTube Data and Analytics APIs for channels you connect.
- Clicks are ours, because the link in the description is a VidWorth short link that redirects to your funnel and logs the click on the way through.
- Leads, calls and payments arrive from the tools you already use — GoHighLevel, Calendly, Cal.com, Typeform, Tally, ClickFunnels — carrying the UTM tags the redirect attached.
- The join happens on
utm_content, which holds the YouTube video id. That is what turns "a booking" into "a booking from that video".
One domain, on purpose
www.vidworth.co. There is no app. or go. subdomain to allow-list. Clients who want their own branded link host can point one at us instead — see Tracked links.Quick start
Roughly fifteen minutes, most of it waiting for the first YouTube sync. Everything below is expanded in its own section.
- Create an account at
https://www.vidworth.co/signup— Google or email and password. You get your own isolated workspace; nobody else can see it until you invite them. - Connect a YouTube channel. One OAuth consent per channel. We read videos and view stats, and only write to a video when you explicitly ask us to.
- Create a tracked link pointing at the funnel, booking page or offer the channel sends people to.
- Place it on a video — into the description, the pinned first comment, or both. Every edit is backed up for one-click undo.
- Connect where conversions happen — your GoHighLevel sub-account, Calendly, or a form tool — so bookings and opt-ins flow back in automatically.
- Read the dashboard. Views, unique clicks, CTR, leads, booked calls and booking rate, per video and per channel.
Connect a YouTube channel
Settings → Channels → Connect channel starts a Google sign-in. Pick the Google account that manages the channel — for a Brand Account, that is an account listed as an owner or manager of the channel, not merely a subscriber.
What we ask for and why
| Permission | What we do with it |
|---|---|
| Read your channel and videos | List uploads, titles, thumbnails and view counts |
| Read YouTube Analytics | Per-day view figures, so CTR is measured against the right window |
| Manage your YouTube account | Two explicit actions only: writing a tracked link into a description, and posting a comment or reply when you write one |
Description edits are non-destructive
Disconnecting
Disconnect a channel from Settings at any time. Historical clicks and bookings stay so past reports remain readable; syncing stops immediately. You can also revoke access from your Google account's security page — we treat a revoked token as a disconnect on the next sync rather than retrying forever.
Tracked links
A tracked link is a short URL on our domain that logs a click and immediately redirects to your destination. It looks like this:
https://www.vidworth.co/r/abc123When someone follows it, we append the attribution tags to your destination URL and send them on with a 302:
https://your-funnel.com/offer
?utm_source=youtube
&utm_medium=organic
&utm_campaign=<channel>
&utm_content=<youtube video id>
&tid=<click id>- Parameters you already set win. If your destination URL already has a
utm_campaign, we leave it alone rather than overwriting your own tagging. utm_contentcarries the video id — that single parameter is what makes per-video attribution possible, so don't strip it in a redirect chain.tidis a click id and gives exact one-to-one attribution when your form or scheduler passes it through.
The tags stay put
Those parameters used to survive exactly one page. A router pushing a new route, a click on your own nav, a refresh, a link opened in a new tab — any of those rebuilt the URL and the campaign was gone, so the booking or the payment three pages later arrived naming nothing.
The site script fixes that. It reads the tags once, keeps them for 90 days on your own domain, and from then on:
- Puts them back in the address bar on every page and after every client-side route change, with
history.replaceState— no reload, no extra history entry, no change to where the visitor is on the page. - Writes them onto your links as they are clicked, including a middle-click, a cmd-click and “Copy link address”.
- Carries them to your funnel vendors — Calendly, Cal.com, Tally, Typeform, Stripe, Whop and the rest — with the click id placed in whichever parameter that vendor forwards to its webhook. Other domains are never told anything.
- Fills scheduler and form embeds on your page. A Calendly or Tally iframe cannot read the URL of the page it sits in, so we write the tags onto its
srcbefore anyone books. - Fills hidden tracking fields your form already declares (
tid,utm_sourceand friends). Fields you did not declare are never added, and a value you already set is never replaced.
Nothing already on a URL is overwritten — if a page arrives tagged utm_source=newsletter, it stays newsletter. Switches, all optional:
window.vidworthStickyUrl = false; // stop rewriting the address bar
window.vidworthDecorateLinks = false; // stop rewriting links on click
window.vidworthDecorateEmbeds = false; // stop touching iframes
window.vidworthFillFields = false; // stop filling hidden fields
window.vidworthDecorateHosts = ["book.yourbrand.com"]; // your other domains
VidWorthUtms(); // the campaign in force right now
VidWorthAttribution(); // first touch, latest touch, click id, visitor id
VidWorthDecorateUrl(href); // for a URL your own JavaScript buildsUnique clicks and bots
The headline click number is unique, non-bot clicks. We de-duplicate repeats from the same visitor within 24 hours, and known crawlers and link-preview fetchers are excluded — otherwise pasting a link into a chat app would inflate the count before a human ever saw it. Raw IP addresses are never stored; an IP is hashed with a daily-rotating salt purely to tell two visitors apart.
Branded link domains
An unfamiliar agency domain in a description costs clicks. A client can point their own host — say go.clientbrand.com — at us with a CNAME and set it on their channel; their links then use their own brand while everything else stays identical. The exact CNAME target is shown on the channel's link-domain screen. Everything is done from that screen — no DNS provider settings beyond the one record, and nothing to configure on the hosting side.
A branded domain is a gateway, not a mirror: it serves only that channel's tracked links and shared reports. Any other page opened on it — including the bare domain — redirects to the channel's default destination, so the app itself never appears under the client's domain.
Placing links on videos
From a video's page, or in bulk from the Videos list, you can:
- Add to description — inserts the tracked link, keeping the rest of the description intact.
- Post as first comment — posts as the channel, ready to pin.
- Undo — restores the description exactly as it was before our edit.
Bulk placement runs across a selection of videos and reports per-video success or failure rather than stopping at the first error. Each video gets its own link, so a click can always be traced to the video that produced it.
Placement is never automatic without you
GoHighLevel
Connecting your HighLevel sub-account sends contacts, form submissions and appointments into VidWorth as they happen, attributed to the video that produced them. We only ever read from HighLevel — nothing in your CRM is created, edited or deleted by this app.
Installing is free
Install it
- In HighLevel, open Settings → Integrations (or the App Marketplace) and install VidWorth.
- Choose the sub-account (location) you want to connect, and approve the read-only permissions on the consent screen.
- You land back in VidWorth with the location connected. If you started from VidWorth instead, use Integrations → GoHighLevel → Connect and pick the same sub-account.
- Pick the channel this sub-account belongs to. One HighLevel location can feed several channels — each gets its own copy of every conversion.
What we read
| Permission | Why |
|---|---|
| Locations (read-only) | Confirm which sub-account was connected and label it |
| Contacts (read-only) | Receive new contacts and form submissions as leads |
| Forms (read-only) | Name the form a submission came from |
| Calendar events (read-only) | Receive appointments as booked calls, including cancellations |
| Orders (read-only) | Attribute revenue to the video that produced the buyer |
| Invoices (read-only) | Count invoices as revenue when they are paid |
Read-only, and revocable
Making the attribution work
HighLevel needs to receive the UTM tags for a lead to land on the right video. Two things make that happen:
- Send traffic through a tracked link so the destination page is loaded with
utm_contentandtidin the URL. - Let HighLevel capture them. HighLevel records UTM parameters on the contact automatically as its attribution source. For the strongest match, add hidden fields named
utm_contentandtidto your form or survey and let HighLevel pre-fill them from the query string.
A conversion that arrives with no usable tags is not thrown away or guessed at — it shows up in an honest bucket like YouTube, unattributed or Direct / unknown, described under Reading the numbers.
Wiring it by hand instead
If you would rather not install the app, a HighLevel Workflow → Webhook action works too. The Integrations page shows a per-channel URL of the form:
https://www.vidworth.co/api/webhooks/crm/<channelId>POST the contact or appointment payload there. This path is for manual wiring only — the installed app uses a single app-wide endpoint and routes each delivery by the location id inside the payload.
Other integrations
Every integration is connected per channel, from Integrations. OAuth connections register their own webhook automatically; the rest give you a URL to paste.
| Tool | Connect by | What arrives |
|---|---|---|
| Calendly | OAuth | Booked and cancelled invitees, with intake answers |
| Cal.com | OAuth | Bookings and cancellations, signature-verified |
| Typeform | OAuth | Form responses as leads |
| Tally | Webhook URL | Form submissions as leads |
| ClickFunnels 2.0 | Webhook URL | Opt-ins and orders |
| Anything else | Generic webhook URL | Opt-ins, bookings or payments you POST to us |
Signatures matter
Duplicate protection
Deliveries are idempotent per conversion. If a vendor retries, or you run both the tracking script and a webhook for the same tool, the conversion is recorded once. The de-duplication key is the conversion, never the person — a lead's second booking is a second booking, not a redelivery of the first.
VidWorth Pixel
Your pixel. One first-party script, on every page of any site you own, scoped to one channel. Copy it from the VidWorth Pixel card on Plugins, where the install step also has the exact instructions for WordPress, Webflow, Shopify, Wix, Squarespace, Framer, Tag Manager and a React app.
<script>
!function(w){w.VidWorthQ=w.VidWorthQ||[];"Track Optin Lead Identify Reset Signup Login PlanView Onboarding Checkout Purchase Subscription OptOut OptIn".split(" ").forEach(function(n){var k="VidWorth"+n;w[k]||(w[k]=function(){w.VidWorthQ.push([n,arguments])},w[k].__vwStub=1)})}(window);
</script>
<script async src="https://www.vidworth.co/api/script/<channelId>"></script>Both tags, in that order. The first is a queue: the second is async, so for the first second or so of a page load none of the VidWorth… functions exist yet, and a call made in that window would otherwise vanish without an error. The queue catches those and replays them the moment the real script runs — which matters most for the events fired nearest page load, like a button above the fold or a thank-you page that converts and immediately navigates away.
With nothing else configured it records page views (including client-side route changes), form submissions with their answers, clicks on booking links, scroll depth and time on page, and it keeps the click id from the URL for 90 days so a form submitted days later still attributes to the right video. It sets no advertising cookies, never captures a password or a card field, and follows no one across other sites.
If you run a product rather than a landing page
A landing page converts by submitting a form, and all of that is in the markup. A product’s funnel — signup, onboarding, pricing, checkout, renewal — is not in the markup at all, so the site says when each one happens:
// Who this person is in YOUR system. Do this one first.
VidWorthIdentify(user.id, { source: "supabase", email: user.email, plan: "pro" });
VidWorthReset(); // on sign-out
VidWorthSignup({ email, fields: { "Referred by": "YouTube" } });
VidWorthOnboarding("company_details", { index: 2, total: 5, fields: { ... } });
VidWorthPlanView({ meta: { plan: "quarterly" } });
VidWorthCheckout({ orderId, provider: "stripe", amount, currency: "USD" });
VidWorthSubscription({ status: "renewed", plan: "Pro", amount: 49, currency: "USD" });
VidWorthTrack("anything_else", { meta: { ... } });
VidWorthClickId(); // the click id, for your own backend
VidWorthDebug(); // prove the install from the consoleVidWorthIdentify is the one that matters. It binds your own user id — a Supabase auth.users.id, a Clerk id, an internal integer — to the person, and from that call onwards every event carries it automatically. That id is the join between what we know (which video, which click, which campaign) and what you know (the account, the plan, the usage, the renewals).
The same events from your backend
Most of a product’s important moments happen with no browser open: a renewal on a billing cron, a refund from a support desk, a cancellation as a row update. Send those server-side against the same user id, and because that call is authenticated it is allowed to carry money — a renewal recorded this way lands in your revenue, attributed to the video that produced the customer.
POST https://www.vidworth.co/api/v1/events
Authorization: Bearer <API key with the conversions:write scope>
{
"channelId": "<channelId>",
"event": "subscription",
"userId": "<the same id you pass to VidWorthIdentify>",
"userSource": "supabase",
"externalId": "<your id for this charge — stops a retry double-counting>",
"subscription": { "status": "renewed", "plan": "Pro", "amount": 49, "currency": "USD" }
}An event sent from both the browser and your backend is recorded once, not twice. A subscription event from a browser moves funnel counts and never revenue — anyone with devtools open could forge one, so money only ever enters the ledger from a signed webhook, an authenticated call like the one above, or a person entering it by hand.
Reading the numbers
The metrics
| Metric | Definition |
|---|---|
| Views | YouTube's own figure for the video, over the selected range |
| Unique clicks | Distinct non-bot visitors who followed the tracked link |
| CTR | Unique clicks ÷ views |
| Leads | Form opt-ins and contacts received from connected tools |
| Booked calls | Appointments received, cancellations excluded |
| Booking rate | Booked calls ÷ unique clicks |
Attribution buckets
Every conversion lands in exactly one bucket, and all buckets are always shown. Hiding the unattributed ones would make the attributed numbers look better and the totals wrong:
| Bucket | When |
|---|---|
| Video | utm_content matches a video we know — full credit to that video |
| YouTube, unattributed | Came from YouTube (utm_source=youtube) but no video id survived |
| Other source | Carried UTM tags from somewhere that isn't YouTube |
| Direct / unknown | Arrived with no tags at all — typed the URL, or the tags were stripped |
A big unattributed bucket is a fixable problem
Leads, bookings & revenue
Leads is the person-level view: every contact we have seen for a channel, the video that produced them, the answers they gave, and every touch in between. Two conversions that share an email or a click id are recognised as the same person rather than counted as two.
Bookings lists calls with their attribution bucket and their intake answers. Transactions records payments received from connected checkout tools, so a video's row can carry revenue and not just call volume.
Every list exports to CSV from the button in its header, honouring the filters and date range you have applied.
Syncing & automation
Conversions arrive in real time over webhooks. YouTube data is pulled on a schedule, because YouTube's APIs are quota-limited and its analytics figures settle over hours rather than seconds:
| Job | Frequency | What it does |
|---|---|---|
| New uploads | Every 15 minutes | Notices videos published since the last check |
| Views | Hourly | Refreshes view counts for recent videos |
| Full video sync | Nightly | Reconciles the whole catalogue |
| Daily stats | Nightly | Pulls per-day analytics for accurate ranges |
Sync now on any channel forces an immediate refresh. View counts you see in YouTube Studio can lead ours by up to a few hours — YouTube's public figure and its analytics figure disagree with each other too, and we report the analytics one because it is the one that can be sliced by date.
Email we send
We write from two addresses, and it is worth knowing which is which: hello@vidworth.co for anything about your account or your numbers, and support@vidworth.co for answers to questions you have asked. Filing rules on the two work independently, and replying to either reaches a person.
| From | When | Can you turn it off? | |
|---|---|---|---|
| Password reset | hello@ | You ask for one | No — it answers your own request |
| Welcome | hello@ | Once, when you sign up | Yes |
| Subscription confirmation | hello@ | A plan starts or changes | Yes |
| Weekly summary | hello@ | Monday mornings | Yes |
| Booked call alert | hello@ | Seconds after a call is booked | Yes |
| Support receipt and replies | support@ | You write in | No — it is the answer to your message |
Only four of those can be switched off. The two that cannot are the ones answering something you just did — turning them off would leave you stuck mid-task with no way back.
The weekly summary is the other half of the picture: it covers the calendar week that has just closed — Monday to Sunday, not a rolling seven days, so each one can be read against the last. It carries views, tracked clicks, leads, booked calls and revenue per channel, with the change against the week before. A week with no activity sends nothing at all: a recurring email that reports zeroes is one you would rightly start ignoring.
The daily report arrives each morning at 7am in your channel's own timezone, covering the day that just closed: views, tracked clicks, form submissions, booked calls and revenue, each against the day before, plus what produced them and where in the world the clicks came from. A day with nothing on it sends nothing — a recurring email that reports zeroes is one you would rightly start ignoring.
Bookings reach you instantly — in the app, not by email
Every member of a workspace gets their own copy and their own switch — two people sharing an agency account can want different amounts of mail. Change it under Settings → Email preferences, or use the unsubscribe button your mail client shows next to the sender. Both take effect immediately; neither needs you to contact us.
Replying works
AI assistant & MCP
The console has a built-in assistant that answers questions about your own data — "which video produced the most booked calls last month?" — and can prepare actions like a bulk placement for you to approve. In the console it never writes to YouTube, arms an automation or deletes anything without an explicit approval step you see first.
MCP has no approval card — your client provides one
VidWorth also exposes a remote MCP endpoint, so an external client such as Claude can query your workspace directly. Settings shows the endpoint URL for your deployment along with the connection steps. It authenticates with OAuth and is scoped to your workspace — the same data you can see in the dashboard, and nothing else.
Data & security
- Tokens are encrypted at rest with AES-256-GCM, and are never logged or displayed.
- No raw IP addresses. An IP is one-way hashed with a rotating daily salt to estimate unique clicks, then discarded.
- Emails are stored as a one-way hash, so a lead can be recognised across tools without us keeping a readable address list.
- Workspace isolation. Data is visible only to members of the workspace that owns the channel. Sign-in is open; access is governed by membership and invites.
- Webhook signatures are verified for every vendor that signs its deliveries.
- Google data is handled under the Google API Services User Data Policy, including the Limited Use requirements. It is never sold and never used for advertising.
Full detail is in the Privacy Policy and Terms of Service. Deletion requests go to support.
Troubleshooting
Clicks are showing but leads are not
The conversion tool isn't reaching us, or it is reaching us and being bucketed as unattributed. Check the integration's status on the Integrations page — it records the last delivery it received and any error. If deliveries are arriving, the tags are being lost between the click and the form; see the tip under Reading the numbers.
Everything lands in "Direct / unknown"
Traffic is reaching your funnel without going through a tracked link, or a redirect on your side is dropping the query string. Open the tracked link yourself and confirm the parameters survive all the way to the page with the form on it.
A channel stopped syncing
Google access was revoked, or the account no longer manages the channel. Reconnect it from Settings — history is preserved.
The connect button for a tool is missing
That integration has no credentials configured on this deployment, so it is hidden rather than shown broken. Ask us to enable it.
A booking was counted twice
Usually two paths for the same tool — the tracking script and a webhook, or two workflows pointing at the same endpoint. Tell us which conversion and we'll trace the delivery.
Get help
Open the support page and tell us what you expected and what happened instead. Your request is confirmed by email the moment you send it, with a reference to quote. If it involves a specific lead, booking or video, include its link — and attach a screenshot if a number looks wrong. The form takes up to four images, and replying to the confirmation email with more attached puts them on the same request.
