Add Microsoft Clarity, Google Tag Manager, and Search Console disclosures to privacy policy

This commit is contained in:
Atakan Doğan Özban 2026-08-19 11:46:48 +02:00
parent 5bc39d0692
commit 01a7bc7886
8 changed files with 289 additions and 47 deletions

View File

@ -2,21 +2,24 @@ import type { Metadata } from "next";
import { Inter } from "next/font/google";
import "./globals.css";
import { Providers } from "./providers";
import { GoogleAnalytics } from "@/components/GoogleAnalytics";
import {
GoogleTagManager,
GoogleTagManagerNoscript,
} from "@/components/GoogleTagManager";
import { JsonLd } from "@/components/JsonLd";
import { Matomo } from "@/components/Matomo";
import { MicrosoftClarity } from "@/components/MicrosoftClarity";
const inter = Inter({ subsets: ["latin"] });
const SITE_URL = "https://songs2vid.com";
const SITE_NAME = "Songs2VID";
const DEFAULT_TITLE =
"Songs2VID - Fast Audio to Video Converter for YouTube | TunesToTube Alternative";
"Songs2VID - Automated Audio to Video Pipeline for Content Creators";
const DEFAULT_DESCRIPTION =
"Convert MP3, WAV, and audio files into YouTube videos instantly. The fastest, privacy-focused online tool to upload music, beats, and podcasts directly to YouTube.";
const OG_TITLE = "Songs2VID - Fast Audio to Video Converter for YouTube";
const OG_DESCRIPTION =
"Convert MP3 & audio files into YouTube videos instantly without heavy editing.";
const TWITTER_DESCRIPTION = "Convert MP3 & audio files into YouTube videos instantly.";
"Convert MP3/WAV tracks and cover art into YouTube-ready videos instantly. Automated, Docker-ready, and lightweight pipeline.";
const OG_IMAGE = "https://songs2vid.com/og-image.png";
export const metadata: Metadata = {
metadataBase: new URL(SITE_URL),
@ -26,7 +29,16 @@ export const metadata: Metadata = {
},
description: DEFAULT_DESCRIPTION,
keywords: [
"upload mp3 to youtube",
"upload flac to youtube",
"upload wav to youtube",
"mp3 to youtube hd",
"jpg to video",
"mp3 to youtube",
"mp3 to youtube converter",
"upload mp3",
"mp3 uploader",
"youtube upload",
"audio to video converter",
"upload audio to youtube",
"tunestotube alternative",
@ -42,26 +54,26 @@ export const metadata: Metadata = {
canonical: SITE_URL,
},
openGraph: {
title: OG_TITLE,
description: OG_DESCRIPTION,
title: DEFAULT_TITLE,
description: DEFAULT_DESCRIPTION,
url: SITE_URL,
siteName: SITE_NAME,
type: "website",
locale: "en_US",
images: [
{
url: "/logo.png",
width: 512,
height: 512,
url: OG_IMAGE,
width: 1200,
height: 630,
alt: SITE_NAME,
},
],
},
twitter: {
card: "summary_large_image",
title: OG_TITLE,
description: TWITTER_DESCRIPTION,
images: ["/logo.png"],
title: DEFAULT_TITLE,
description: DEFAULT_DESCRIPTION,
images: [OG_IMAGE],
},
robots: {
index: true,
@ -83,9 +95,15 @@ export default function RootLayout({
}>) {
return (
<html lang="en" suppressHydrationWarning>
<head>
<GoogleTagManager />
</head>
<body className={inter.className} suppressHydrationWarning>
<GoogleTagManagerNoscript />
<GoogleAnalytics />
<JsonLd />
<Matomo />
<MicrosoftClarity />
<Providers>{children}</Providers>
</body>
</html>

View File

@ -64,45 +64,71 @@ export default function PrivacyPage() {
uploaded MP3 files to help prefill fields
</li>
<li>Playlist titles and IDs when you create or attach YouTube playlists through the Service</li>
<li>
Optional job callback URLs (<code>webhookUrl</code>) you provide for automation (for
example n8n or Make) - see section 3.5
</li>
</ul>
<h3>3.3 Usage, API, and technical data</h3>
<ul>
<li>
Plan type, monthly credit allocation, credits used, purchased extra credits, quota reset
Plan type (Bedroom Producer / Independent Producer / Developer &amp; Automation /
Enterprise), monthly credit allocation, credits used, purchased extra credits, quota reset
dates, lifetime successful video render count (used for Free-tier watermark policy), and
job processing status
</li>
<li>
Quota reset / extension and API rate-limit extension request history (Pro) when you submit
a request
Quota reset / extension request history for paid plans, and API rate-limit extension
request history for Developer &amp; Automation / Enterprise when you submit a request
</li>
<li>
API key material for Pro users: we store a cryptographic hash and a short non-secret
prefix; the full key is shown once at creation and is not stored in plaintext
API key material for Developer &amp; Automation and Enterprise users: we store a
cryptographic hash and a short non-secret prefix; the full key is shown once at creation
and is not stored in plaintext
</li>
<li>IP address, browser type, device information, and request logs</li>
<li>Error reports and operational diagnostics</li>
<li>
Website and product analytics events collected via Matomo (self-hosted at
analytics.atakanozban.com) to understand traffic and improve the Service — see section
10
analytics.atakanozban.com), Google Analytics (GA4 measurement IDs G-9XCHRS7LJR and G-2V3FSMMPQX),
Google Tag Manager (container GTM-PZL4HXBR), Microsoft Clarity (project y4hxg6t7s6), and
Google Search Console search-performance reports to understand traffic and improve the
Service - see section 10
</li>
</ul>
<h3>3.4 Payment data</h3>
<p>
If you purchase a Pro subscription or Free-plan extra credits, payment processing is handled
by Stripe. We do not store full payment card details on our servers. We may receive and store
billing status, Stripe customer and subscription identifiers, Checkout session or payment
references, purchase amounts, and credit pack size for fulfilled top-ups.
If you purchase an Independent Producer subscription, a Developer &amp; Automation
subscription, an Enterprise arrangement, or Free-plan extra credits, payment processing is
handled by Stripe. We do not store full payment card details on our servers. We may receive
and store billing status, Stripe customer and subscription identifiers, Checkout session or
payment references, plan identifiers, purchase amounts, and credit pack size for fulfilled
top-ups.
</p>
<h3>3.5 Job webhooks and automation callbacks</h3>
<p>
On Developer &amp; Automation and Enterprise plans (and self-hosted deployments where
enabled), you may supply an absolute HTTP(S) callback URL when creating a render job. We
store that URL with the job record and, when encoding or upload reaches a terminal state,
may POST a JSON payload to it. Typical fields include event type, job and item identifiers,
status, optional YouTube video ID, error message, and completion timestamp.
</p>
<p>
You choose the destination (for example your n8n webhook, Make scenario, or your own
server). We do not control how that endpoint stores or shares the payload. Only set URLs you
own or are authorized to use. Delivery is best-effort; we do not guarantee receipt or
retention by the receiving system.
</p>
<h2>4. Why we process your data</h2>
<ul>
<li>
<strong>Contract performance:</strong> to provide video encoding, metadata handling,
playlist actions, API access, and YouTube upload features you request
playlist actions, API access, webhook notifications, and YouTube upload features you
request
</li>
<li>
<strong>Legitimate interests:</strong> to secure our service, prevent abuse, improve
@ -145,18 +171,73 @@ export default function PrivacyPage() {
storage
</li>
<li>
<strong>Stripe:</strong> Pro subscriptions, Free-plan credit top-ups, and related billing
webhooks (
<strong>Stripe:</strong> Independent Producer and Developer &amp; Automation
subscriptions, Free-plan credit top-ups, and related billing webhooks (
<a href="https://stripe.com/privacy" target="_blank" rel="noopener noreferrer">
Stripe Privacy Policy
</a>
)
</li>
<li>
<strong>Your webhook endpoints:</strong> if you configure a job <code>webhookUrl</code>,
we send job status JSON to that URL as described in section 3.5
</li>
<li>
<strong>Matomo (self-hosted analytics):</strong> privacy-friendly analytics we operate at
analytics.atakanozban.com to measure visits and improve Songs2VID. Analytics data stays on
infrastructure we control; we do not sell it to advertising networks.
</li>
<li>
<strong>Google Analytics:</strong> Google LLC processes aggregated usage analytics for our
sites under Google&apos;s terms when the GA4 tags (G-9XCHRS7LJR and G-2V3FSMMPQX) load. See{" "}
<a
href="https://policies.google.com/privacy"
target="_blank"
rel="noopener noreferrer"
>
Google&apos;s Privacy Policy
</a>
.
</li>
<li>
<strong>Google Tag Manager:</strong> Google LLC loads our tag container{" "}
<code>GTM-PZL4HXBR</code>, which may deploy Google Analytics and other measurement tags we
configure. See{" "}
<a
href="https://policies.google.com/privacy"
target="_blank"
rel="noopener noreferrer"
>
Google&apos;s Privacy Policy
</a>
.
</li>
<li>
<strong>Google Search Console:</strong> Google LLC provides search indexing and
performance reports (queries, impressions, clicks, coverage) for songs2vid.com and related
properties we verify. Search Console is a webmaster tool, not a visitor-facing tracker on
every page. See{" "}
<a
href="https://policies.google.com/privacy"
target="_blank"
rel="noopener noreferrer"
>
Google&apos;s Privacy Policy
</a>
.
</li>
<li>
<strong>Microsoft Clarity:</strong> Microsoft Corporation processes usage analytics and
anonymized session recordings and heatmaps (project y4hxg6t7s6). See{" "}
<a
href="https://www.microsoft.com/privacy/privacystatement"
target="_blank"
rel="noopener noreferrer"
>
Microsoft&apos;s Privacy Statement
</a>
.
</li>
</ul>
<p>
These providers process data only as necessary to deliver their services and under
@ -186,8 +267,9 @@ export default function PrivacyPage() {
<p>
We do not sell, share, transfer, or disclose Google user data obtained via Google OAuth /
YouTube APIs to third parties, except as needed to operate the Service infrastructure under
our control or when required by law. Google / YouTube themselves process data when we call
their APIs on your behalf to perform actions you initiate.
our control, when required by law, or when you explicitly configure a job webhook that may
include a YouTube video ID you caused to be published. Google / YouTube themselves process
data when we call their APIs on your behalf to perform actions you initiate.
</p>
<p>
You can revoke Songs2VID&apos;s access to your Google account at any time in{" "}
@ -196,7 +278,7 @@ export default function PrivacyPage() {
target="_blank"
rel="noopener noreferrer"
>
Google Account → Security → Third-party access
Google Account - Security - Third-party access
</a>
. After revocation (or when tokens can no longer be refreshed), we will stop using those
credentials and delete or invalidate stored YouTube OAuth tokens and related connection data
@ -208,18 +290,24 @@ export default function PrivacyPage() {
<ul>
<li>
Uploaded source files and generated outputs are retained only as long as needed to complete
your jobs (typically removed after successful processing/upload or when no longer required)
your jobs (typically removed after successful YouTube upload or when no longer required for
retries)
</li>
<li>
Job metadata (status, titles, YouTube IDs, errors, optional <code>webhookUrl</code>) is
kept while your account remains active and may be purged on account deletion, subject to
short-term backups and troubleshooting logs
</li>
<li>Account data is kept while your account remains active</li>
<li>Billing records may be retained as required by law</li>
<li>Logs are retained for a limited period for security and troubleshooting</li>
<li>
API key hashes are removed when you revoke the key, downgrade from Pro (where applicable),
or delete your account
API key hashes are removed when you revoke the key, leave Developer &amp; Automation /
Enterprise (where applicable), or delete your account
</li>
</ul>
<p>
You may delete your account from <strong>Dashboard → Settings</strong> (account deletion
You may delete your account from <strong>Dashboard - Settings</strong> (account deletion
control) or by emailing{" "}
<a href={`mailto:${LEGAL_OPERATOR.email}`}>{LEGAL_OPERATOR.email}</a>. Deletion removes
account and connection data from active systems subject to legal retention obligations
@ -245,7 +333,7 @@ export default function PrivacyPage() {
<li>Withdraw consent where processing is consent-based</li>
<li>
Lodge a complaint with a supervisory authority (in Hungary, the Nemzeti Adatvédelmi és
Információszabadság Hatóság — NAIH)
Információszabadság Hatóság - NAIH)
</li>
</ul>
<p>
@ -262,11 +350,43 @@ export default function PrivacyPage() {
</p>
<p>
We also use <strong>Matomo</strong>, a self-hosted analytics tool on{" "}
<code>analytics.atakanozban.com</code>, on our website (including the landing page and
dashboard) and documentation site. Matomo helps us understand how people use Songs2VID so we
can improve functionality, reliability, and content. Typical data includes pages viewed,
approximate location derived from IP, device/browser type, referring site, and interaction
events. We configure Matomo for our domains under <code>*.songs2vid.com</code>.
<code>analytics.atakanozban.com</code>, <strong>Google Analytics 4</strong> (measurement
IDs <code>G-9XCHRS7LJR</code> and <code>G-2V3FSMMPQX</code>), and{" "}
<strong>Microsoft Clarity</strong> (project <code>y4hxg6t7s6</code>) on our website
(including the landing page and dashboard) and documentation site. These tools help us
understand how people use Songs2VID so we can improve functionality, reliability, and
content. Typical data includes pages viewed, approximate location derived from IP,
device/browser type, referring site, interaction events, and (for Clarity) anonymized
session recordings and heatmaps. We configure Matomo for our domains under{" "}
<code>*.songs2vid.com</code>. Google Analytics is provided by Google LLC; see{" "}
<a
href="https://policies.google.com/privacy"
target="_blank"
rel="noopener noreferrer"
>
Google&apos;s Privacy Policy
</a>
. Microsoft Clarity is provided by Microsoft Corporation; see{" "}
<a
href="https://www.microsoft.com/privacy/privacystatement"
target="_blank"
rel="noopener noreferrer"
>
Microsoft&apos;s Privacy Statement
</a>
.
</p>
<p>
We also use <strong>Google Tag Manager</strong> (container <code>GTM-PZL4HXBR</code>) to
load and manage measurement tags on our website, including Google Analytics. Tag Manager is
a delivery mechanism; tags it loads may set cookies or collect usage data as described in
this section.
</p>
<p>
We use <strong>Google Search Console</strong> to verify site ownership and review search
indexing and performance reports (such as queries, impressions, and clicks) for
songs2vid.com. Search Console is operated by Google LLC and is not a page-level visitor
tracking pixel.
</p>
<p>
We collect this analytics data to improve the Service, not to sell personal profiles to
@ -280,17 +400,18 @@ export default function PrivacyPage() {
<h2>11. Security</h2>
<p>
We implement appropriate technical and organizational measures to protect your data,
including encryption in transit, encrypted storage of YouTube OAuth tokens at rest, access
controls, and isolated processing environments. No method of transmission or storage is
100% secure.
including encryption in transit, encrypted storage of YouTube OAuth tokens at rest, hashed
API keys, access controls, and isolated processing environments. No method of transmission
or storage is 100% secure.
</p>
<h2>12. International transfers</h2>
<p>
If data is transferred outside your country, we ensure appropriate safeguards such as
standard contractual clauses or equivalent mechanisms where required by law. Google, Stripe,
and infrastructure providers may process data in other countries as described in their
policies.
Microsoft, and infrastructure providers may process data in other countries as described in
their policies. Webhook destinations you configure may also receive data in other countries
under your control.
</p>
<h2>13. Children</h2>

View File

@ -0,0 +1,28 @@
import Script from "next/script";
/** Primary GA4 property (songs2vid.com). */
const GA_MEASUREMENT_ID = "G-9XCHRS7LJR";
/** Additional GA4 property — both must remain configured. */
const GA_MEASUREMENT_ID_SECONDARY = "G-2V3FSMMPQX";
/**
* Google Analytics 4 (gtag.js) for songs2vid.com / songs2yt.com.
* Loaded once from the root layout; both measurement IDs stay active.
*/
export function GoogleAnalytics() {
return (
<>
<Script
src={`https://www.googletagmanager.com/gtag/js?id=${GA_MEASUREMENT_ID}`}
strategy="afterInteractive"
/>
<Script id="google-analytics" strategy="afterInteractive">{`
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '${GA_MEASUREMENT_ID}');
gtag('config', '${GA_MEASUREMENT_ID_SECONDARY}');
`}</Script>
</>
);
}

View File

@ -0,0 +1,34 @@
import Script from "next/script";
const GTM_ID = "GTM-PZL4HXBR";
/**
* Google Tag Manager container GTM-PZL4HXBR.
* Place in <head> as early as possible (beforeInteractive).
*/
export function GoogleTagManager() {
return (
<Script id="google-tag-manager" strategy="beforeInteractive">{`
(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','${GTM_ID}');
`}</Script>
);
}
/** GTM noscript iframe — immediately after opening <body>. */
export function GoogleTagManagerNoscript() {
return (
<noscript>
<iframe
src={`https://www.googletagmanager.com/ns.html?id=${GTM_ID}`}
height={0}
width={0}
style={{ display: "none", visibility: "hidden" }}
title="Google Tag Manager"
/>
</noscript>
);
}

View File

@ -0,0 +1,19 @@
import Script from "next/script";
const CLARITY_ID = "y4hxg6t7s6";
/**
* Microsoft Clarity session analytics for songs2vid.com.
* Loaded once from the root layout alongside GA and Matomo.
*/
export function MicrosoftClarity() {
return (
<Script id="microsoft-clarity" strategy="afterInteractive">{`
(function(c,l,a,r,i,t,y){
c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)};
t=l.createElement(r);t.async=1;t.src="https://www.clarity.ms/tag/"+i;
y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y);
})(window, document, "clarity", "script", "${CLARITY_ID}");
`}</Script>
);
}

View File

@ -1,7 +1,7 @@
import { SUPPORT_EMAIL, SALES_EMAIL, QUOTA_REQUEST_EMAIL } from "@/lib/plans";
import { BRAND_DOMAIN, BRAND_NAME } from "@/lib/branding";
export const LEGAL_LAST_UPDATED = "August 3, 2026";
export const LEGAL_LAST_UPDATED = "August 19, 2026";
export const LEGAL_OPERATOR = {
name: BRAND_NAME,

View File

@ -25,10 +25,22 @@ const config: Config = {
},
scripts: [
{
src: 'https://www.googletagmanager.com/gtag/js?id=G-9XCHRS7LJR',
async: true,
},
{
src: '/js/gtag-config.js',
async: true,
},
{
src: '/js/matomo.js',
async: true,
},
{
src: '/js/clarity.js',
async: true,
},
],
presets: [
@ -97,6 +109,10 @@ const config: Config = {
label: 'REST API',
to: '/docs/api/overview',
},
{
label: 'n8n integration',
to: '/docs/n8n',
},
],
},
{

View File

@ -0,0 +1,6 @@
/* Microsoft Clarity for docs.songs2vid.com */
(function (c, l, a, r, i, t, y) {
c[a] = c[a] || function () { (c[a].q = c[a].q || []).push(arguments); };
t = l.createElement(r); t.async = 1; t.src = "https://www.clarity.ms/tag/" + i;
y = l.getElementsByTagName(r)[0]; y.parentNode.insertBefore(t, y);
})(window, document, "clarity", "script", "y4hxg6t7s6");