ultimate-jekyll-manager 0.0.117 → 0.0.119

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/CLAUDE.md +616 -138
  2. package/README.md +108 -0
  3. package/TODO.md +1 -1
  4. package/dist/assets/js/core/auth.js +8 -11
  5. package/dist/assets/js/core/cookieconsent.js +24 -17
  6. package/dist/assets/js/core/exit-popup.js +15 -12
  7. package/dist/assets/js/core/social-sharing.js +8 -4
  8. package/dist/assets/js/libs/auth/pages.js +14 -13
  9. package/dist/assets/js/libs/dev.js +192 -129
  10. package/dist/assets/js/libs/prerendered-icons.js +27 -0
  11. package/dist/assets/js/pages/account/index.js +4 -3
  12. package/dist/assets/js/pages/account/sections/api-keys.js +2 -6
  13. package/dist/assets/js/pages/account/sections/connections.js +101 -59
  14. package/dist/assets/js/pages/account/sections/delete.js +83 -84
  15. package/dist/assets/js/pages/account/sections/referrals.js +29 -29
  16. package/dist/assets/js/pages/account/sections/security.js +51 -71
  17. package/dist/assets/js/pages/admin/notifications/new/index.js +17 -10
  18. package/dist/assets/js/pages/blog/index.js +7 -5
  19. package/dist/assets/js/pages/contact/index.js +6 -33
  20. package/dist/assets/js/pages/download/index.js +3 -2
  21. package/dist/assets/js/pages/payment/checkout/index.js +6 -6
  22. package/dist/assets/js/pages/payment/checkout/modules/processors-main.js +2 -2
  23. package/dist/assets/js/pages/payment/checkout/modules/session.js +4 -4
  24. package/dist/assets/js/pages/pricing/index.js +5 -2
  25. package/dist/assets/themes/classy/css/components/_cards.scss +2 -2
  26. package/dist/defaults/_.env +6 -0
  27. package/dist/defaults/_.gitignore +7 -1
  28. package/dist/defaults/dist/_includes/core/body.html +18 -3
  29. package/dist/defaults/dist/_includes/core/foot.html +1 -0
  30. package/dist/defaults/dist/_includes/themes/classy/frontend/sections/nav.html +51 -36
  31. package/dist/defaults/dist/_layouts/blueprint/admin/notifications/new.html +13 -2
  32. package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/about.html +84 -42
  33. package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/account/index.html +67 -35
  34. package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/blog/index.html +72 -58
  35. package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/blog/post.html +46 -29
  36. package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/contact.html +36 -16
  37. package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/download.html +111 -73
  38. package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/index.html +111 -56
  39. package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/pricing.html +127 -81
  40. package/dist/defaults/dist/pages/pricing.md +7 -0
  41. package/dist/defaults/dist/pages/test/libraries/lazy-loading.html +1 -1
  42. package/dist/gulp/tasks/defaults.js +210 -1
  43. package/firebase-debug.log +504 -0
  44. package/package.json +5 -5
package/README.md CHANGED
@@ -282,6 +282,114 @@ Add the `.btn-action` class to protect custom elements that trigger important ac
282
282
  - `_test_trialEligible=false`: User is not eligible for trial
283
283
  * `_test_cardProcessor`: Force a specific payment processor for testing (e.g., `_test_cardProcessor=stripe` or `_test_cardProcessor=paypal`)
284
284
 
285
+ ## JavaScript API
286
+
287
+ ### Ultimate Jekyll Libraries
288
+
289
+ Ultimate Jekyll provides helper libraries in `src/assets/js/libs/` that can be imported as needed in your page modules.
290
+
291
+ #### Prerendered Icons Library
292
+
293
+ The prerendered icons library provides access to icons defined in page frontmatter. Icons are rendered server-side for optimal performance.
294
+
295
+ **Import:**
296
+ ```javascript
297
+ import { getPrerenderedIcon } from '__main_assets__/js/libs/prerendered-icons.js';
298
+ ```
299
+
300
+ **Function: `getPrerenderedIcon(iconName)`**
301
+
302
+ **Parameters:**
303
+ - `iconName` (string) - Name of the icon to retrieve (matches `data-icon` attribute in frontmatter)
304
+
305
+ **Returns:**
306
+ - (string) Icon HTML or empty string if not found
307
+
308
+ **Example:**
309
+ ```javascript
310
+ import { getPrerenderedIcon } from '__main_assets__/js/libs/prerendered-icons.js';
311
+
312
+ // Get a pre-rendered icon
313
+ const appleIcon = getPrerenderedIcon('apple');
314
+
315
+ // Use in your page
316
+ document.querySelector('.device-icon').innerHTML = appleIcon;
317
+ ```
318
+
319
+ **Setup:**
320
+ Define icons in your page frontmatter:
321
+ ```yaml
322
+ ---
323
+ prerender_icons:
324
+ - name: "apple"
325
+ class: "fa-3xl"
326
+ - name: "android"
327
+ class: "fa-2xl"
328
+ - name: "chrome"
329
+ class: "fa-lg"
330
+ ---
331
+ ```
332
+
333
+ Icons are automatically rendered in the page HTML and can be retrieved by importing the library function.
334
+
335
+ #### Authorized Fetch Library
336
+
337
+ The authorized fetch library simplifies authenticated API requests by automatically adding Firebase authentication tokens.
338
+
339
+ **Import:**
340
+ ```javascript
341
+ import authorizedFetch from '__main_assets__/js/libs/authorized-fetch.js';
342
+ ```
343
+
344
+ **Function: `authorizedFetch(url, options)`**
345
+
346
+ **Parameters:**
347
+ - `url` (string) - The API endpoint URL
348
+ - `options` (Object) - Request options for wonderful-fetch (method, body, timeout, etc.)
349
+
350
+ **Returns:**
351
+ - (Promise) - The response from the API
352
+
353
+ **Example:**
354
+ ```javascript
355
+ import authorizedFetch from '__main_assets__/js/libs/authorized-fetch.js';
356
+
357
+ // Make an authenticated API call
358
+ const response = await authorizedFetch(serverApiURL, {
359
+ method: 'POST',
360
+ timeout: 30000,
361
+ response: 'json',
362
+ tries: 2,
363
+ body: {
364
+ command: 'user:get-data',
365
+ payload: { id: 'example' }
366
+ }
367
+ });
368
+ ```
369
+
370
+ **How It Works:**
371
+ 1. Retrieves the current Firebase user's ID token automatically
372
+ 2. Adds the token to the request as an `Authorization: Bearer <token>` header
373
+ 3. Makes the request using wonderful-fetch
374
+ 4. Throws an error if no authenticated user is found
375
+
376
+ **Benefits:**
377
+ - No need to manually call `webManager.auth().getIdToken()`
378
+ - No need to add `authenticationToken` to request body
379
+ - Centralized authentication handling
380
+ - Consistent authentication across all API calls
381
+
382
+ #### FormManager Library
383
+
384
+ Custom library for form handling with built-in state management and validation.
385
+
386
+ **Import:**
387
+ ```javascript
388
+ import { FormManager } from '__main_assets__/js/libs/form-manager.js';
389
+ ```
390
+
391
+ **Documentation:** See [form-manager.js](src/assets/js/libs/form-manager.js) for full API and usage examples.
392
+
285
393
  ### Icons
286
394
  * Fontawesome
287
395
  * https://fontawesome.com/search
package/TODO.md CHANGED
@@ -34,7 +34,7 @@ MAKE COMPONENTS? ASK CLAUDE HOW AND IF ITS POSSIBLE
34
34
 
35
35
  FIX SIGNIN/SINGUP FORM
36
36
 
37
- https://192.168.86.69:4000/payment/checkout?product=premium&_test_trialEligible=true&_test_appId=dev&_test_cardProcessor=stripe
37
+ https://192.168.86.69:4000/payment/checkout?product=premium&_dev_trialEligible=true&_dev_appId=dev&_dev_cardProcessor=stripe
38
38
 
39
39
  filter-adaptive-inverse
40
40
 
@@ -1,4 +1,4 @@
1
- import fetch from 'wonderful-fetch';
1
+ import authorizedFetch from '__main_assets__/js/libs/authorized-fetch.js';
2
2
 
3
3
  // Auth Module
4
4
  export default function (Manager, options) {
@@ -32,7 +32,7 @@ export default function (Manager, options) {
32
32
  console.log('[Auth] state changed:', state);
33
33
 
34
34
  // Set user ID for analytics tracking
35
- setAnalyticsUserId(user);
35
+ setAnalyticsUserId(user, webManager);
36
36
 
37
37
  // Check if we're in the process of signing out
38
38
  if (authSignout === 'true' && user) {
@@ -119,9 +119,10 @@ function redirect(url, returnUrl) {
119
119
  window.location.href = newURL;
120
120
  }
121
121
 
122
- function setAnalyticsUserId(user) {
122
+ function setAnalyticsUserId(user, webManager) {
123
123
  const userId = user?.uid;
124
124
  const email = user?.email;
125
+ const metaPixelId = webManager.config.tracking['meta-pixel'];
125
126
 
126
127
  // Short-circuit if no user
127
128
  if (!userId) {
@@ -129,7 +130,7 @@ function setAnalyticsUserId(user) {
129
130
  gtag('set', { user_id: null });
130
131
 
131
132
  // Facebook Pixel - Clear advanced matching
132
- fbq('init', fbq.pixelId, {});
133
+ fbq('init', metaPixelId, {});
133
134
 
134
135
  // TikTok Pixel - Clear user data
135
136
  ttq.identify({});
@@ -147,7 +148,7 @@ function setAnalyticsUserId(user) {
147
148
  });
148
149
 
149
150
  // Facebook Pixel - Set advanced matching with user data
150
- fbq('init', fbq.pixelId, {
151
+ fbq('init', metaPixelId, {
151
152
  external_id: userId,
152
153
  // em: email ? btoa(email.toLowerCase().trim()) : undefined,
153
154
  em: email,
@@ -166,9 +167,6 @@ function setAnalyticsUserId(user) {
166
167
  // Send user metadata to server (affiliate, UTM params, etc.)
167
168
  async function sendUserSignupMetadata(user, webManager) {
168
169
  try {
169
- // Get the auth token
170
- const token = await webManager.auth().getIdToken();
171
-
172
170
  // Get affiliate data from storage
173
171
  const affiliateData = webManager.storage().get('marketing.affiliate', null);
174
172
  const utmData = webManager.storage().get('marketing.utm', null);
@@ -193,11 +191,10 @@ async function sendUserSignupMetadata(user, webManager) {
193
191
  // Get server API URL
194
192
  const serverApiURL = webManager.getApiUrl() + '/backend-manager';
195
193
 
196
- // Make API call to reset API key
197
- const response = await fetch(serverApiURL, {
194
+ // Make API call to send signup metadata
195
+ const response = await authorizedFetch(serverApiURL, {
198
196
  method: 'POST',
199
197
  body: {
200
- authenticationToken: token,
201
198
  command: 'user:sign-up',
202
199
  payload: payload
203
200
  }
@@ -310,59 +310,66 @@ export default function (Manager, options) {
310
310
 
311
311
  // Tracking functions
312
312
  function trackCookieBannerShown() {
313
- gtag('event', 'cookie_banner_shown', {
313
+ gtag('event', 'cookie_banner_show', {
314
314
  event_category: 'consent'
315
315
  });
316
- fbq('trackCustom', 'CookieBannerShown');
316
+ fbq('trackCustom', 'CookieBannerShow');
317
317
  ttq.track('ViewContent', {
318
- content_name: 'Cookie Banner'
318
+ content_id: 'cookie-banner-show',
319
+ content_type: 'product',
320
+ content_name: 'Cookie Banner Show'
319
321
  });
320
322
  }
321
323
 
322
324
  function trackCookieAccepted() {
323
- gtag('event', 'cookie_consent_accepted', {
325
+ gtag('event', 'cookie_consent_accept', {
324
326
  event_category: 'consent',
325
327
  consent_type: config.type
326
328
  });
327
- fbq('trackCustom', 'CookieConsentAccepted');
329
+ fbq('trackCustom', 'CookieConsentAccept');
328
330
  ttq.track('ClickButton', {
329
- content_name: 'Cookie Consent Accept',
330
- content_type: 'consent'
331
+ content_id: 'cookie-consent-accept',
332
+ content_type: 'product',
333
+ content_name: 'Cookie Consent Accept'
331
334
  });
332
335
  }
333
336
 
334
337
  function trackCookieDenied() {
335
- gtag('event', 'cookie_consent_denied', {
338
+ gtag('event', 'cookie_consent_deny', {
336
339
  event_category: 'consent',
337
340
  consent_type: config.type
338
341
  });
339
- fbq('trackCustom', 'CookieConsentDenied');
342
+ fbq('trackCustom', 'CookieConsentDeny');
340
343
  ttq.track('ClickButton', {
341
- content_name: 'Cookie Consent Deny',
342
- content_type: 'consent'
344
+ content_id: 'cookie-consent-deny',
345
+ content_type: 'product',
346
+ content_name: 'Cookie Consent Deny'
343
347
  });
344
348
  }
345
349
 
346
350
  function trackCookieAutoAccepted(trigger) {
347
- gtag('event', 'cookie_consent_auto_accepted', {
351
+ gtag('event', 'cookie_consent_auto_accept', {
348
352
  event_category: 'consent',
349
353
  trigger: trigger
350
354
  });
351
- fbq('trackCustom', 'CookieConsentAutoAccepted', {
355
+ fbq('trackCustom', 'CookieConsentAutoAccept', {
352
356
  trigger: trigger
353
357
  });
354
358
  ttq.track('ViewContent', {
355
- content_name: 'Cookie Consent Auto Accept',
356
- content_type: trigger
359
+ content_id: 'cookie-consent-auto-accept',
360
+ content_type: 'product',
361
+ content_name: 'Cookie Consent Auto Accept'
357
362
  });
358
363
  }
359
364
 
360
365
  function trackCookiePolicyReopened() {
361
- gtag('event', 'cookie_policy_reopened', {
366
+ gtag('event', 'cookie_policy_reopen', {
362
367
  event_category: 'consent'
363
368
  });
364
- fbq('trackCustom', 'CookiePolicyReopened');
369
+ fbq('trackCustom', 'CookiePolicyReopen');
365
370
  ttq.track('ClickButton', {
371
+ content_id: 'cookie-policy-reopen',
372
+ content_type: 'product',
366
373
  content_name: 'Cookie Policy Reopen'
367
374
  });
368
375
  }
@@ -177,20 +177,21 @@ export default function (Manager, options) {
177
177
 
178
178
  // Tracking functions
179
179
  function trackExitPopupShown() {
180
- gtag('event', 'exit_popup_shown', {
180
+ gtag('event', 'exit_popup_show', {
181
181
  event_category: 'engagement',
182
182
  event_label: config.title,
183
183
  page_path: window.location.pathname
184
184
  });
185
185
 
186
- fbq('trackCustom', 'ExitPopupShown', {
187
- content_name: config.title,
186
+ fbq('trackCustom', 'ExitPopupShow', {
187
+ content_name: 'Exit Popup Show',
188
188
  page_path: window.location.pathname
189
189
  });
190
190
 
191
191
  ttq.track('ViewContent', {
192
- content_name: 'Exit Popup',
193
- content_type: config.title
192
+ content_id: 'exit-popup-show',
193
+ content_type: 'product',
194
+ content_name: 'Exit Popup Show'
194
195
  });
195
196
  }
196
197
 
@@ -207,24 +208,26 @@ export default function (Manager, options) {
207
208
  });
208
209
 
209
210
  ttq.track('ClickButton', {
210
- content_name: 'Exit Popup CTA',
211
- content_type: config.okButton?.text || 'OK'
211
+ content_id: 'exit-popup-click',
212
+ content_type: 'product',
213
+ content_name: 'Exit Popup Click'
212
214
  });
213
215
  }
214
216
 
215
217
  function trackExitPopupDismissed() {
216
- gtag('event', 'exit_popup_dismissed', {
218
+ gtag('event', 'exit_popup_dismiss', {
217
219
  event_category: 'engagement',
218
220
  event_label: config.title
219
221
  });
220
222
 
221
- fbq('trackCustom', 'ExitPopupDismissed', {
222
- content_name: config.title
223
+ fbq('trackCustom', 'ExitPopupDismiss', {
224
+ content_name: 'Exit Popup Dismiss'
223
225
  });
224
226
 
225
227
  ttq.track('ViewContent', {
226
- content_name: 'Exit Popup Dismissed',
227
- content_type: config.title
228
+ content_id: 'exit-popup-dismiss',
229
+ content_type: 'product',
230
+ content_name: 'Exit Popup Dismiss'
228
231
  });
229
232
  }
230
233
  };
@@ -289,6 +289,8 @@ export default function (Manager, options) {
289
289
 
290
290
  // Tracking functions
291
291
  function trackShare(platformKey, shareConfig) {
292
+ const platformName = platforms[platformKey]?.name || platformKey;
293
+
292
294
  gtag('event', 'share', {
293
295
  method: platformKey,
294
296
  content_type: 'article',
@@ -302,9 +304,9 @@ export default function (Manager, options) {
302
304
  });
303
305
 
304
306
  ttq.track('Share', {
305
- content_name: shareConfig.title,
306
- content_url: shareConfig.url,
307
- share_method: platformKey
307
+ content_id: `social-share-${platformKey}`,
308
+ content_type: 'product',
309
+ content_name: `Social Share ${platformName}`
308
310
  });
309
311
  }
310
312
 
@@ -319,7 +321,9 @@ export default function (Manager, options) {
319
321
  });
320
322
 
321
323
  ttq.track('ClickButton', {
322
- content_name: 'Copy Link'
324
+ content_id: 'social-share-copy-link',
325
+ content_type: 'product',
326
+ content_name: 'Social Share Copy Link'
323
327
  });
324
328
  }
325
329
  };
@@ -620,6 +620,7 @@ export default function (Manager) {
620
620
 
621
621
  function trackLogin(method, user) {
622
622
  const userId = user.uid;
623
+ const methodName = method.charAt(0).toUpperCase() + method.slice(1);
623
624
 
624
625
  // Google Analytics 4
625
626
  gtag('event', 'login', {
@@ -629,21 +630,22 @@ export default function (Manager) {
629
630
 
630
631
  // Facebook Pixel
631
632
  fbq('trackCustom', 'Login', {
633
+ content_name: `Account Login ${methodName}`,
632
634
  method: method,
633
- status: 'success'
634
635
  });
635
636
 
636
637
  // TikTok Pixel
637
638
  ttq.track('Login', {
638
- content_name: 'Account',
639
- content_id: userId,
640
- status: 'success'
639
+ content_id: `account-login-${method}`,
640
+ content_type: 'product',
641
+ content_name: `Account Login ${methodName}`
641
642
  });
642
643
  }
643
644
 
644
645
  // Analytics tracking functions
645
646
  function trackSignup(method, user) {
646
647
  const userId = user.uid;
648
+ const methodName = method.charAt(0).toUpperCase() + method.slice(1);
647
649
 
648
650
  // Google Analytics 4
649
651
  gtag('event', 'sign_up', {
@@ -653,17 +655,15 @@ export default function (Manager) {
653
655
 
654
656
  // Facebook Pixel
655
657
  fbq('track', 'CompleteRegistration', {
656
- content_name: 'Account',
657
- status: 'success',
658
- value: 0,
659
- currency: 'USD'
658
+ content_name: `Account Registration ${methodName}`,
659
+ method: method,
660
660
  });
661
661
 
662
662
  // TikTok Pixel
663
663
  ttq.track('CompleteRegistration', {
664
- content_name: 'Account',
665
- content_id: userId,
666
- status: 'success'
664
+ content_id: `account-registration-${method}`,
665
+ content_type: 'product',
666
+ content_name: `Account Registration ${methodName}`
667
667
  });
668
668
  }
669
669
 
@@ -683,8 +683,9 @@ export default function (Manager) {
683
683
 
684
684
  // TikTok Pixel
685
685
  ttq.track('SubmitForm', {
686
- content_name: 'Password Reset',
687
- content_type: 'account_recovery'
686
+ content_id: 'password-reset',
687
+ content_type: 'product',
688
+ content_name: 'Password Reset'
688
689
  });
689
690
  }
690
691
  }