Sign up for Morning Wire:
Our flagship newsletter breaks down the biggest headlines of the day.
{
if (value !== undefined && value !== null && value !== ”) {
url.searchParams.set(key, value);
}
});
return url.toString();
} catch (err) {
console.warn(‘Unable to build referrer URL with UTM params:’, err);
return window.location.href;
}
}
function nlLoadRecaptchaScriptNLMW25(siteKey, callback) {
if (typeof window.grecaptcha !== ‘undefined’) {
callback && callback();
return;
}
const existingScript = document.querySelector(‘script[src*=”recaptcha/api.js”]’);
if (existingScript) {
const checkInterval = setInterval(() => {
if (typeof window.grecaptcha !== ‘undefined’) {
clearInterval(checkInterval);
callback && callback();
}
}, nlRecaptchaCheckIntervalNLMW25);
return;
}
const script = document.createElement(‘script’);
script.src = `https://www.google.com/recaptcha/api.js?render=${encodeURIComponent(siteKey)}`;
script.async = true;
script.defer = true;
script.onload = () => callback && callback();
script.onerror = () => {
console.error(‘Failed to load reCAPTCHA script’);
callback && callback(false);
};
document.head.appendChild(script);
}
function nlWaitForRecaptchaNLMW25(callback, maxAttempts = nlRecaptchaMaxAttemptsNLMW25) {
let attempts = 0;
const checkRecaptcha = () => {
attempts++;
if (
typeof window.grecaptcha !== ‘undefined’ &&
typeof window.grecaptcha.execute === ‘function’
) {
callback(true);
} else if (attempts token && token.length > 0 ? token : null)
.catch(error => {
const errorMsg = error?.message || String(error);
if (
errorMsg.includes(‘No reCAPTCHA clients’) ||
errorMsg.includes(‘not initialized’) ||
errorMsg.includes(‘Invalid site key’)
) {
throw new Error(‘recaptcha_failed’);
}
throw error;
});
}
const nlEmbedsNLMW25 = document.querySelectorAll(‘[data-ap-newsletter-embed-nlmw25]’);
nlEmbedsNLMW25.forEach((rootNLMW25, idxNLMW25) => {
const formNLMW25 = rootNLMW25.querySelector(‘.ap-newsletter-form-nlmw25’);
const emailInputNLMW25 = rootNLMW25.querySelector(‘.ap-newsletter-input-nlmw25’);
const checkboxNLMW25 = rootNLMW25.querySelector(‘.ap-newsletter-checkbox-nlmw25’);
const errorElNLMW25 = rootNLMW25.querySelector(‘.ap-newsletter-error-nlmw25’);
const helpElNLMW25 = rootNLMW25.querySelector(‘.ap-newsletter-help-nlmw25’);
const botFieldNLMW25 = rootNLMW25.querySelector(‘.ap-newsletter-bot-field-nlmw25’);
const recaptchaDivNLMW25 = rootNLMW25.querySelector(‘.ap-newsletter-recaptcha-nlmw25’);
let nlIsSubmittingNLMW25 = false;
const newsletterListNLMW25 = nlConfigNLMW25.defaultNewsletterList;
const recaptchaSiteKeyNLMW25 = nlConfigNLMW25.recaptchaSiteKey;
const requestReferrerNLMW25 = nlBuildReferrerUrlNLMW25(nlConfigNLMW25.referrerUtmParams);
const emailIdNLMW25 = `nl-email-nlmw25-${idxNLMW25}`;
const helpIdNLMW25 = `nl-help-nlmw25-${idxNLMW25}`;
const errIdNLMW25 = `nl-error-nlmw25-${idxNLMW25}`;
const recaptchaIdNLMW25 = `recaptcha-nlmw25-${idxNLMW25}`;
emailInputNLMW25.id = emailIdNLMW25;
helpElNLMW25.id = helpIdNLMW25;
errorElNLMW25.id = errIdNLMW25;
if (recaptchaDivNLMW25) {
recaptchaDivNLMW25.id = recaptchaIdNLMW25;
if (recaptchaSiteKeyNLMW25) {
recaptchaDivNLMW25.setAttribute(‘data-sitekey’, recaptchaSiteKeyNLMW25);
}
}
emailInputNLMW25.setAttribute(‘aria-describedby’, `${helpIdNLMW25} ${errIdNLMW25}`);
const nlSetErrorNLMW25 = (msg) => {
errorElNLMW25.textContent = msg || ”;
errorElNLMW25.style.display = msg ? ‘block’ : ‘none’;
};
const nlHideErrorNLMW25 = () => nlSetErrorNLMW25(”);
const nlSetSubmittedNLMW25 = () => {
rootNLMW25.classList.add(‘is-submitted-nlmw25’);
emailInputNLMW25.value = ‘SUBMITTED’;
emailInputNLMW25.style.fontWeight = ‘bold’;
emailInputNLMW25.setAttribute(‘readonly’, ‘readonly’);
emailInputNLMW25.setAttribute(‘aria-invalid’, ‘false’);
nlHideErrorNLMW25();
};
const nlSubscribeNLMW25 = (tokenNLMW25) => {
if (nlIsSubmittingNLMW25) return;
if (botFieldNLMW25?.value) {
console.warn(‘Bot field filled –‘, botFieldNLMW25.value);
nlSetErrorNLMW25(nlConfigNLMW25.messages.botBlocked);
return;
}
const emailNLMW25 = String(emailInputNLMW25.value || ”).trim();
const emailOkNLMW25 = nlIsValidEmailNLMW25(emailNLMW25);
const disclaimerOkNLMW25 = checkboxNLMW25.checked;
if (!emailOkNLMW25 && !disclaimerOkNLMW25) {
nlSetErrorNLMW25(nlConfigNLMW25.messages.invalidBoth);
emailInputNLMW25.setAttribute(‘aria-invalid’, ‘true’);
emailInputNLMW25.focus();
return;
}
if (!emailOkNLMW25) {
nlSetErrorNLMW25(nlConfigNLMW25.messages.invalidEmail);
emailInputNLMW25.setAttribute(‘aria-invalid’, ‘true’);
emailInputNLMW25.focus();
return;
}
if (!disclaimerOkNLMW25) {
nlSetErrorNLMW25(nlConfigNLMW25.messages.disclaimerRequired);
checkboxNLMW25.focus();
return;
}
nlIsSubmittingNLMW25 = true;
const headersNLMW25 = { ‘Content-Type’: ‘application/json’ };
if (tokenNLMW25) {
headersNLMW25[nlConfigNLMW25.recaptchaHeader] = tokenNLMW25;
}
fetch(nlConfigNLMW25.apiUrl, {
method: ‘POST’,
headers: headersNLMW25,
body: JSON.stringify({
emailId: emailNLMW25,
newsLetterListToSubscribe: newsletterListNLMW25
}),
/*
This is the key change:
send the current page URL + UTM params as the referrer.
Example:
https://…/article/… ?utm_source=embed
*/
referrer: requestReferrerNLMW25,
referrerPolicy: ‘strict-origin-when-cross-origin’
})
.then(response =>
response.json()
.then(data => ({ status: response.status, data }))
.catch(() => ({ status: response.status, data: null }))
)
.then(result => {
nlIsSubmittingNLMW25 = false;
const hasVerificationErrorNLMW25 = result.data && (
result.data.message?.includes(‘Verification Failed’) ||
result.data.error?.includes(‘Verification Failed’)
);
if (hasVerificationErrorNLMW25) {
nlSetErrorNLMW25(nlConfigNLMW25.messages.verificationFailed);
return;
}
if (result.status === 200) {
if (typeof window.NLSignup === ‘function’) {
try { window.NLSignup(emailNLMW25); } catch (err) {}
}
window.dispatchEvent(new CustomEvent(‘nl:newsletterSignup:nlmw25’, {
detail: {
email: emailNLMW25,
source: ‘Morning Wire Embed’,
newsletters: newsletterListNLMW25,
referrer: requestReferrerNLMW25
}
}));
nlSetSubmittedNLMW25();
} else {
const errorMsgNLMW25 =
result.data?.message ||
result.data?.error ||
nlConfigNLMW25.messages.genericError;
nlSetErrorNLMW25(errorMsgNLMW25);
}
})
.catch(error => {
nlIsSubmittingNLMW25 = false;
console.error(‘Newsletter subscription error:’, error);
nlSetErrorNLMW25(nlConfigNLMW25.messages.genericError);
});
};
const nlAttemptRecaptchaNLMW25 = () => {
if (!recaptchaSiteKeyNLMW25) {
nlWaitForRecaptchaNLMW25(isAvailable => {
if (!isAvailable) {
nlSetErrorNLMW25(nlConfigNLMW25.messages.recaptchaRequired);
nlIsSubmittingNLMW25 = false;
return;
}
nlExecuteRecaptchaNLMW25()
.then(token => nlSubscribeNLMW25(token))
.catch(() => nlSubscribeNLMW25(null));
});
return;
}
nlLoadRecaptchaScriptNLMW25(recaptchaSiteKeyNLMW25, success => {
if (success === false) {
nlSetErrorNLMW25(nlConfigNLMW25.messages.recaptchaLoadFail);
nlIsSubmittingNLMW25 = false;
return;
}
nlWaitForRecaptchaNLMW25(isAvailable => {
if (!isAvailable) {
nlSetErrorNLMW25(nlConfigNLMW25.messages.recaptchaRequired);
nlIsSubmittingNLMW25 = false;
return;
}
const runExecuteNLMW25 = () => {
nlExecuteRecaptchaNLMW25()
.then(token => nlSubscribeNLMW25(token))
.catch(error => {
if (error?.message === ‘recaptcha_failed’) {
nlSetErrorNLMW25(nlConfigNLMW25.messages.recaptchaFailed);
nlIsSubmittingNLMW25 = false;
} else {
console.warn(‘reCAPTCHA error:’, error);
nlSubscribeNLMW25(null);
}
});
};
if (typeof window.grecaptcha.ready === ‘function’) {
window.grecaptcha.ready(runExecuteNLMW25);
} else {
runExecuteNLMW25();
}
});
});
};
formNLMW25.addEventListener(‘submit’, e => {
e.preventDefault();
if (rootNLMW25.classList.contains(‘is-submitted-nlmw25’) || nlIsSubmittingNLMW25) return;
nlHideErrorNLMW25();
nlAttemptRecaptchaNLMW25();
});
emailInputNLMW25.addEventListener(‘input’, () => {
nlHideErrorNLMW25();
emailInputNLMW25.setAttribute(‘aria-invalid’, ‘false’);
});
checkboxNLMW25.addEventListener(‘change’, nlHideErrorNLMW25);
});
})(NL_DEFAULT_CONFIG_NLMW25);
]]>