TL;DR
Subscribe sounds like the right Meta event for a newsletter. Meta reserves it for "a paid subscription", and Google says outright that newsletter sign-ups belong on generate_lead. So name the event first: Lead on Meta, generate_lead in GA4. Then wire it in a custom pixel, and which route you need comes down to who draws the form, your theme or a popup app. The signup is the one moment before a purchase when you have the visitor's email in hand, so pass it to Meta. And keep the event out of your purchase bidding, because anyone can fake it from a browser console.
Key Takeaways
- Meta's
Subscribemeans "a paid subscription";Leadis "When a sign up is completed" [1]. A newsletter signup is aLead. - GA4's reference says "newsletter sign-ups" should use
generate_lead, and keepssign_upfor "signed up for an account" [3]. - The theme's newsletter form posts to
/contactwith a hiddenform_typeofcustomer[6], which a custom pixel can recognise in theform_submittedevent [5]. - Custom pixels run in a
laxsandbox iframe that "cannot access the top frame" [4], so a popup app's window event needs a theme script that republishes it withShopify.analytics.publish[7]. - Meta only treats the email as manual advanced matching when it sits in the
fbq('init')call [2]. The pixel below calls init when the signup arrives, with the email. - Shopify warns custom events "can be published by users, other developers and even visitors from their browser console" [7]. Report on signups; don't bid on them.
- New custom pixels require Marketing and Analytics permission by default in regions such as the EEA and UK [8], so signups from visitors who declined are missing on purpose.
Which event should a newsletter signup fire?
Lead on Meta, generate_lead in GA4. Meta's standard events reference defines the three candidates like this [1]:
| Meta event | Meta's definition | Use it for | GA4 counterpart |
|---|---|---|---|
Lead |
"When a sign up is completed." | Newsletter or SMS list signups | generate_lead |
CompleteRegistration |
"When a registration form is completed." | Creating a customer account | sign_up |
Subscribe |
"When a person applies to a start a paid subscription for a product or service you offer." (sic) | A paid subscription order | the order's purchase
|
GA4 settles its half without room for argument. In the notes on its lead events, Google writes: "To track initial lead acquisition, such as form submissions, newsletter sign-ups, or demo requests, use the generate_lead event" [3]. sign_up "indicates that a user has signed up for an account" [3]. Those two sit outside the ecommerce set covered in the GA4 recommended ecommerce events canon.
Meta's table is looser. Its example for CompleteRegistration is "A person submits a completed subscription or signup form" [1], which makes it an easy pick for newsletters. If yours has fired CompleteRegistration for a year and custom conversions or audiences hang off it, keeping it is defensible, because anything built on the old event name stops filling the day you rename. What doesn't hold up is Subscribe. Firing it on a newsletter tells Meta's optimizer, every time someone types an email into a popup, that a paid subscription just started. Paid subscriptions are their own tracking job, covered in tracking subscription orders on Shopify.
TikTok, Pinterest and the rest have their own lead events; the reasoning carries over.
What your tracking app already sends, and what it doesn't
Nothing about the signup, on any plan. WeltPixel Conversion Tracking tracks commerce: browsing, cart and checkout events, and the purchase from the order record. It sends no signup, lead or registration event to any platform, and its storefront pixel listens only to Shopify's standard commerce events, so there's no setting to switch on and no way to route a form through it. The order-side data the app receives from Shopify is about orders and refunds, and a signup isn't an order.
If you run Klaviyo, the app can load Klaviyo's onsite script. That script is what shows Klaviyo's forms, and the app loads it without reporting anything about those forms to your ad platforms. Klaviyo tracking on Shopify covers why it loads the script at all.
So the signup is a custom pixel you add yourself, in Settings → Customer events. Shopify applies its customer privacy settings to custom pixels [8].
Who draws the form decides the route
Two kinds of form collect newsletter emails on a Shopify store, and a custom pixel sees them differently.
The theme's own form is built with Liquid's form 'customer' tag, which Shopify documents for "building a list of emails from a newsletter signup" [6]. It renders as a form posting to /contact with a hidden input named form_type set to customer [6]. Shopify's form_submitted DOM event reports each submitted form's action and the name, type and value of its elements [5], so a custom pixel can recognise the newsletter form and read the email from it.
A popup app's form works differently. Klaviyo's forms announce activity by sending an event called klaviyoForms to the window, and the submit type "fires when a visitor submits the main conversion action of a form" and "will only fire once per form", with the email in metaData when the form collected one [9]. That event lives on the storefront page. A custom pixel runs in what Shopify calls a lax sandbox, an iframe that "cannot access the top frame" [4], so it can't hear it. The consequences of that iframe for Meta matching are laid out in why match quality drops when the Meta Pixel runs through GTM on Shopify. This job needs a bridge, and Shopify provides one.
A script in theme.liquid can call Shopify.analytics.publish('my_store:event_name', event_data), and "When custom customer events are published they can be accessed by all custom pixels and app pixels" [7]. The custom pixel subscribes to that name and reads the data from customData [7].
Whether a given popup's submission also triggers form_submitted is something we haven't verified for Klaviyo or any other app. Don't assume either way. The console log in the pixel below tells you on your own store in one test.
How do you wire both routes in one pixel?
Paste this into a new custom pixel of its own. Meta documents the email as the third parameter of the fbq('init') call, and says values left out of the base code "will not be treated as manual advanced matching values" [2]. So the pixel loads Meta's library straight away but holds the init call until a signup hands it an email, which the pixel then hashes with SHA-256 [2]. It sends no PageView, because your existing Meta setup already does.
// Settings → Customer events → Add custom pixel
const META_PIXEL_ID = 'YOUR_PIXEL_ID';
// Meta's loader, without the init and PageView lines
!function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function(){n.callMethod?
n.callMethod.apply(n,arguments):n.queue.push(arguments)};if(!f._fbq)f._fbq=n;
n.push=n;n.loaded=!0;n.version='2.0';n.queue=[];t=b.createElement(e);t.async=!0;
t.src=v;s=b.getElementsByTagName(e)[0];s.parentNode.insertBefore(t,s)}(window,
document,'script','https://connect.facebook.net/en_US/fbevents.js');
let leadSent = false;
function sendLead(email) {
if (leadSent) return; // one Lead per page, even if both routes fire
leadSent = true;
const em = typeof email === 'string' ? email.trim().toLowerCase() : '';
fbq('init', META_PIXEL_ID, em ? { em } : {});
fbq('track', 'Lead');
}
// Route 1: the theme's own newsletter form
analytics.subscribe('form_submitted', (event) => {
const form = event.data.element;
const fields = form.elements || [];
// Test log: field names and types only, never the email. Delete after testing.
console.log('form_submitted', form.action, fields.map((f) =>
f.name === 'form_type' ? 'form_type=' + f.value : f.name + ':' + f.type));
const isNewsletter = (form.action || '').includes('/contact') &&
fields.some((f) => f.name === 'form_type' && f.value === 'customer');
if (!isNewsletter) return;
const emailField = fields.find((f) =>
f.type === 'email' || /email/i.test(f.name || '') || /email/i.test(f.id || ''));
sendLead(emailField ? emailField.value : '');
});
// Route 2: a popup app's form, republished from the theme
analytics.subscribe('yourstore:newsletter_signup', (event) => {
sendLead(event.customData && event.customData.email);
});
The email field is matched by type, or by "email" in its name or id, as Shopify's own form_submitted example does [5]. If neither fits your theme, the console log shows what to match on.
For a Klaviyo popup, add the bridge to layout/theme.liquid (Online Store → Themes → Edit code), on a duplicate theme first:
<script>
var SIGNUP_FORM_IDS = ['AbC123']; // your Klaviyo signup form IDs
window.addEventListener('klaviyoForms', function (e) {
if (!e.detail || e.detail.type !== 'submit') return;
if (SIGNUP_FORM_IDS.indexOf(e.detail.formId) === -1) return;
var email = e.detail.metaData && e.detail.metaData.email;
if (window.Shopify && Shopify.analytics) {
Shopify.analytics.publish('yourstore:newsletter_signup', { email: email || '' });
}
});
</script>
Klaviyo's submit also fires on forms with no subscription action, and on an email-plus-SMS form it fires for whichever field comes first [9], so the bridge passes only the forms you list. Each form's ID is in its URL in Klaviyo [9]. Shopify asks for a prefix on custom event names [7]; replace yourstore with something only your store uses, in both snippets.
GA4 follows the same decision, and this pixel deliberately leaves it out. Send generate_lead from wherever your Google tag already runs. If that's inside a custom pixel, read the GTM article above first, since every tag loaded in the sandbox inherits the same iframe.
How do you know the Lead actually fired?
The theme form is a plain POST to /contact [6], so the browser leaves the page on submit and the pixel has a short window to get the request out. This pixel does its Meta setup at the moment of submit, so test the theme-form route in a fresh private window, not a warm tab. Only seeing the event arrive proves it did.
- Save and connect the pixel in
Settings → Customer events. - Open the storefront with the browser console open and set to preserve the log across page loads, subscribe with a test address, and read the
form_submittedline. Theactionand theform_typeelement should match the check in the code. - In Meta Events Manager, open your dataset's Test events tab and confirm one
Leadarrived. - Trigger the popup, subscribe with a second address, and confirm exactly one
Leadarrived for it. - Delete the
console.logline.
If the test address never shows up, check the pixel's customer privacy setting before the code. By default, new custom pixels require Marketing and Analytics permission [8], and Shopify's page on custom pixel code calls out regions like the European Economic Area and the United Kingdom [8]. Visitors who declined won't send a Lead from this pixel, on purpose.
The email is the payoff, and the event stays out of bidding
Events before a purchase usually carry less for Meta to match on than the purchase does, and the gap between funnel events and Purchase explains why. The signup is the exception. It's the one moment before checkout where the visitor has just typed their email into your page, and the code above hands it to Meta in the init call. A Lead that carries an email gives Meta something to match on. One without it gives Meta far less.
Then keep it where it belongs:
- Send it without a value. Meta requires
currencyandvalueonPurchaseand nothing onLead[1]. GA4 recommends a value if you markgenerate_leadas a key event [3]; use a nominal, documented one if you do, and set it up with the GA4 key events guide. - Don't make it the optimization event of a Sales campaign. If a low-volume store needs a proxy, pick one from the purchase path.
- If you import
generate_leadinto Google Ads, keep it secondary, as the primary conversion action guide explains.
The reason is in Shopify's own documentation for the bridge. "Custom events can be published by users, other developers and even visitors from their browser console" [7]. Anyone who opens dev tools on your store can type one line and create a signup. That's fine for a prospecting audience or a weekly count. It's a bad thing to put money behind.
FAQ
Should a newsletter signup be Lead or CompleteRegistration on Meta?
Lead is the closer fit: Meta defines it as "When a sign up is completed" and keeps CompleteRegistration for "a registration form" [1]. If you've used CompleteRegistration for a long time and audiences depend on it, staying consistent is reasonable. Avoid Subscribe, which Meta defines as a paid subscription.
Which GA4 event should I use for newsletter signups?
generate_lead. Google's reference names "newsletter sign-ups" as a generate_lead use and keeps sign_up for account creation [3].
Does WeltPixel Conversion Tracking track newsletter signups?
No. The app sends commerce events and purchases, on every plan, and no signup or lead event to any platform. A custom pixel in Settings → Customer events is the way to add one.
Can a Shopify custom pixel hear a Klaviyo form submission?
Not directly. Klaviyo sends klaviyoForms to the storefront window [9], and a custom pixel's sandbox "cannot access the top frame" [4]. A few lines in theme.liquid republish it with Shopify.analytics.publish, and the pixel subscribes to that [7].
Lead events on top, purchases underneath
WeltPixel Conversion Tracking sends the purchase from the Shopify order to up to nine destinations, and Meta's copy carries hashed customer details from the order. Add the signup pixel on top of it, name it Lead, and let the purchase stay the event your campaigns bid on.
Sources
- Meta for Developers, Meta Pixel "Reference" (standard events: Lead, CompleteRegistration, Subscribe, Purchase), developers.facebook.com/docs/meta-pixel/reference, accessed September 30, 2026
- Meta for Developers, "Advanced Matching" (manual advanced matching in
fbq('init'); SHA-256 hashing), developers.facebook.com/docs/meta-pixel/advanced/advanced-matching, accessed September 30, 2026 - Google for Developers, GA4 "Recommended events" reference (
generate_lead,sign_up), developers.google.com/analytics/devguides/collection/ga4/reference/events, accessed September 30, 2026 - Shopify.dev, "About web pixels" (strict and lax sandboxes), shopify.dev/docs/apps/build/marketing-analytics/pixels, accessed September 30, 2026
- Shopify.dev, Web Pixels API,
form_submitted, shopify.dev/docs/api/web-pixels-api/dom-events/form_submitted, accessed September 30, 2026 - Shopify.dev, Liquid
formtag (form 'customer'), shopify.dev/docs/api/liquid/tags/form, accessed September 30, 2026 - Shopify.dev, Web Pixels API, "Emitting data" (custom events), shopify.dev/docs/api/web-pixels-api/emitting-data, accessed September 30, 2026
- Shopify Help Center, custom pixel code (default Marketing and Analytics permissions), help.shopify.com/en/manual/promoting-marketing/pixels/custom-pixels/code, accessed September 30, 2026
- Klaviyo Developers, "Track Klaviyo form activity using JavaScript", developers.klaviyo.com/en/docs/track_klaviyo_form_activity_using_javascript, accessed September 30, 2026