PageSourceSearch

https://gabrielmohr.com/wp-content/plugins/convertkit/resources/frontend/js/convertkit.js?ver=3.3.5

js gabrielmohr.com collected 2026-10-04 21:35:31 UTC 6,286 bytes, 232 lines download raw bytes

1/**
2 * Frontend functionality for subscribers and tags.
3 *
4 * @since   1.9.6
5 *
6 * @author ConvertKit
7 */
8
9/**
10 * Gets the subscriber ID for the given email address, storing
11 * it in the `ck_subscriber_id` cookie if it exists.
12 *
13 * Typically called when the user completes a ConvertKit Form
14 * that has either "Auto-confirm new subscribers" or
15 * "Send subscriber to thank you page" enabled (both scenarios
16 * include a ck_subscriber_id).
17 *
18 * @since   1.9.6
19 *
20 * @param {string} emailAddress Email Address
21 */
22function convertStoreSubscriberEmailAsIDInCookie(emailAddress) {
23	if (convertkit.debug) {
24		console.log('convertStoreSubscriberEmailAsIDInCookie');
25		console.log(emailAddress);
26	}
27
28	fetch(convertkit.ajaxurl, {
29		method: 'POST',
30		headers: {
31			'Content-Type': 'application/x-www-form-urlencoded',
32			'X-WP-Nonce': convertkit.nonce,
33		},
34		body: new URLSearchParams({
35			email: emailAddress,
36		}),
37	})
38		.then(function (response) {
39			if (convertkit.debug) {
40				console.log(response);
41			}
42
43			return response.json();
44		})
45		.then(function (result) {
46			if (convertkit.debug) {
47				console.log(result);
48			}
49
50			// Emit custom event with subscriber ID.
51			convertKitEmitCustomEvent('convertkit_user_subscribed', {
52				id: result.id,
53				email: emailAddress,
54			});
55		})
56		.catch(function (error) {
57			if (convertkit.debug) {
58				console.error(error);
59			}
60		});
61}
62
63/**
64 * Remove the url subscriber_id url param
65 *
66 * The 'ck_subscriber_id' should only be set on URLs included on
67 * links from a ConvertKit email with no other URL parameters.
68 * This function removes the parameters so a customer won't share
69 * a URL with their subscriber ID in it.
70 *
71 * @param {string} url URL.
72 */
73function convertKitRemoveSubscriberIDFromURL(url) {
74	// Parse URL.
75	const url_object = new URL(url);
76	const ck_subscriber_id = url_object.searchParams.get('ck_subscriber_id');
77
78	// If ck_subscriber_id is null, it's not included in the URL.
79	// Don't modify the URL.
80	if (ck_subscriber_id === null) {
81		return;
82	}
83
84	// Remove ck_subscriber_id from URL params.
85	url_object.searchParams.delete('ck_subscriber_id');
86
87	// Get title and string of parameters.
88	const title = document.getElementsByTagName('title')[0].innerHTML;
89	let params = url_object.searchParams.toString();
90
91	// Only add '?' if there are parameters.
92	if (params.length > 0) {
93		params = '?' + params;
94	}
95
96	// Update history.
97	window.history.replaceState(
98		null,
99		title,
100		url_object.pathname + params + url_object.hash
101	);
102
103	// Emit custom event with the removed subscriber ID.
104	convertKitEmitCustomEvent('kit_subscriber_id_removed_from_url', {
105		id: ck_subscriber_id,
106	});
107}
108
109/**
110 * Utility function to pause for the given number of milliseconds
111 *
112 * @since   1.9.6
113 * @param {number} milliseconds Number of milliseconds to pause for.
114 */
115function convertKitSleep(milliseconds) {
116	const start = new Date().getTime();
117	for (let i = 0; i < 1e7; i++) {
118		if (new Date().getTime() - start > milliseconds) {
119			break;
120		}
121	}
122}
123
124/**
125 * Emit a custom event with optional detail data.
126 *
127 * This function creates and dispatches a custom event with the specified
128 * event name and detail data.
129 *
130 * @since 2.5.0
131 *
132 * @param {string} eventName   The name of the custom event to emit.
133 * @param {Object} [detail={}] Optional detail data to include with the event.
134 */
135function convertKitEmitCustomEvent(eventName, detail) {
136	const event = new CustomEvent(eventName, { detail });
137	document.dispatchEvent(event);
138}
139
140/* eslint-disable no-unused-vars */
141/**
142 * Handles form submissions when reCAPTCHA is enabled.
143 *
144 * @param {string} token reCAPTCHA token.
145 */
146function convertKitRecaptchaFormSubmit(token) {
147	// Find submit button with the data-callback attribute.
148	const submitButton = document.querySelector(
149		'[type="submit"][data-callback="convertKitRecaptchaFormSubmit"]'
150	);
151
152	// Get the parent form of the submit button.
153	const form = submitButton.closest('form');
154
155	// Submit the form.
156	form.submit();
157}
158
159// Scope the function to the window object as webpack will wrap everything in a closure,
160// resulting in the function not being available globally.
161window.convertKitRecaptchaFormSubmit = convertKitRecaptchaFormSubmit;
162/* eslint-enable no-unused-vars */
163
164/**
165 * Register events on frontend.
166 *
167 * @since   3.2.0
168 */
169if (typeof convertkit !== 'undefined') {
170	document.addEventListener('DOMContentLoaded', function () {
171		// Removes `ck_subscriber_id` from the URI.
172		convertKitRemoveSubscriberIDFromURL(window.location.href);
173
174		// Store subscriber ID as a cookie from the email address used when a ConvertKit Form is submitted.
175		document.addEventListener('click', function (e) {
176			// Check if the form submit button was clicked, or the span element was clicked and its parent is the form submit button.
177			if (
178				!e.target.matches('.formkit-submit') &&
179				(!e.target.parentElement ||
180					!e.target.parentElement.matches('.formkit-submit'))
181			) {
182				if (convertkit.debug) {
183					console.log('not a ck form');
184				}
185
186				return;
187			}
188
189			// Get email address.
190			const emailAddress = document.querySelector(
191				'input[name="email_address"]'
192			).value;
193
194			// If the email address is empty, don't attempt to get the subscriber ID by email.
195			if (!emailAddress.length) {
196				if (convertkit.debug) {
197					console.log('email empty');
198				}
199
200				return;
201			}
202
203			// If the email address is invalid, don't attempt to get the subscriber ID by email.
204			const validator =
205				/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
206			if (!validator.test(emailAddress.toLowerCase())) {
207				if (convertkit.debug) {
208					console.log('email not an email address');
209				}
210
211				return;
212			}
213
214			// Wait a moment before sending the AJAX request.
215			convertKitSleep(2000);
216			convertStoreSubscriberEmailAsIDInCookie(emailAddress);
217		});
218
219		// Set a cookie if any scripts with data-kit-limit-per-session attribute exist.
220		if (
221			document.querySelectorAll('script[data-kit-limit-per-session="1"]')
222				.length > 0
223		) {
224			document.cookie = 'ck_non_inline_form_displayed=1; path=/';
225			if (convertkit.debug) {
226				console.log(
227					'Set `ck_non_inline_form_displayed` cookie for non-inline form limit'
228				);
229			}
230		}
231	});
232}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.