Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Website: Integrate Google Analytics and dynamic sitemap.xml setup #2494

Merged
merged 7 commits into from
Feb 21, 2025

Conversation

OchiengPaul442
Copy link
Contributor

@OchiengPaul442 OchiengPaul442 commented Feb 21, 2025

Summary of Changes (What does this PR do?)

  • Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change.

Status of maturity (all need to be checked before merging):

  • I've tested this locally
  • I consider this code done
  • This change ready to hit production in its current state

Screenshots (optional)

image
image

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features
    • Enabled analytics tracking to gather better insights when configured.
    • Deployed endpoints that serve a robots.txt file and a dynamically generated sitemap, improving site discovery.
    • Introduced a Google Analytics component for seamless integration.
    • Enhanced the newsletter subscription form with automatic reset and clearer user feedback.
    • Updated the Careers page messaging to offer more informative guidance regarding current hiring status.
    • Introduced a responsive image layout for the African Cities and Communities pages, improving visual consistency across devices.

@OchiengPaul442 OchiengPaul442 self-assigned this Feb 21, 2025
Copy link

coderabbitai bot commented Feb 21, 2025

📝 Walkthrough

Walkthrough

The pull request integrates Google Analytics into the application by conditionally rendering a new GA component within the RootLayout, based on an environment-provided measurement ID. Additionally, new GET endpoints are created to serve dynamically generated robots.txt and sitemap.xml responses. The newsletter component is enhanced with an auto-reset mechanism and improved user feedback, while the Careers page now displays a more informative message when no positions are available.

Changes

File(s) Summary
website2/src/app/layout.tsx, website2/src/components/GoogleAnalytics.tsx Integrates Google Analytics: Adds conditional rendering of the GA component and defines the GA tracking using Next.js Script.
website2/src/app/robots.txt/route.ts, website2/src/app/sitemap.xml/route.ts Adds new GET endpoints: Generates robots.txt and sitemap.xml content with static routes and proper headers.
website2/src/components/layouts/NewsLetter.tsx Updates newsletter form: Implements auto-reset functionality with improved layout and error handling.
website2/src/views/careers/CareerPage.tsx Updates the careers page: Modifies the message displayed when no open positions are found.
website2/.env.sample Adds a new environment variable for Google Analytics measurement ID.
website2/src/views/solutions/AfricanCities/AfricanCities.tsx, website2/src/views/solutions/communities/CommunityPage.tsx Refactors image display logic and layout for responsiveness in respective components.

Possibly related PRs

Suggested reviewers

  • Baalmart
  • Codebmk

Poem

Code whispers secrets in every line,
Analytics awaken with a measured shine.
Robots and sitemaps craft paths anew,
Newsletter resets, keeping UI true.
Careers message inspires dreams to align,
Cheers to progress—a code masterpiece divine!

Warning

Review ran into problems

🔥 Problems

Errors were encountered while retrieving linked issues.

Errors (1)
  • JIRA integration encountered authorization issues. Please disconnect and reconnect the integration in the CodeRabbit UI.

📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fcc2744 and 026a677.

📒 Files selected for processing (1)
  • website2/src/app/sitemap.xml/route.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • website2/src/app/sitemap.xml/route.ts
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build-push-website2-deploy-preview

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai or @coderabbitai title anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (4)
website2/src/components/GoogleAnalytics.tsx (1)

15-19: Consider adding error handling for the GA script.

The script loading looks good, but consider adding an onError handler to track script loading failures.

 <Script
   src={`https://www.googletagmanager.com/gtag/js?id=${measurementId}`}
   strategy="afterInteractive"
+  onError={(e) => {
+    console.error('Error loading Google Analytics:', e);
+  }}
   // Optionally, use strategy="lazyOnload" if you experience performance issues.
 />
website2/src/app/layout.tsx (1)

37-37: Add type safety for environment variable.

Consider adding type checking for the GA measurement ID.

-  const GA_MEASUREMENT_ID = process.env.NEXT_PUBLIC_GA_MEASUREMENT_ID;
+  const GA_MEASUREMENT_ID = process.env.NEXT_PUBLIC_GA_MEASUREMENT_ID as string | undefined;
+  
+  // Validate measurement ID format
+  if (GA_MEASUREMENT_ID && !GA_MEASUREMENT_ID.startsWith('G-')) {
+    console.warn('Invalid Google Analytics measurement ID format');
+  }
website2/src/app/sitemap.xml/route.ts (1)

58-58: Consider using actual last modification dates.

Instead of using the current date for all URLs, consider tracking actual content modification dates.

-          <lastmod>${new Date().toISOString().split('T')[0]}</lastmod>
+          <lastmod>${getLastModifiedDate(path)}</lastmod>

Add this helper function:

async function getLastModifiedDate(path: string): Promise<string> {
  // You could fetch this from your CMS or content metadata
  // For now, fallback to current date
  return new Date().toISOString().split('T')[0];
}
website2/src/components/layouts/NewsLetter.tsx (1)

46-63: Consider increasing the auto-reset timer duration.

While the auto-reset functionality is well-implemented with proper cleanup, 5 seconds might be too short for users to read the success message. Consider increasing it to 8-10 seconds for better user experience.

-      }, 5000);
+      }, 8000);
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1e8c6a3 and f216525.

📒 Files selected for processing (6)
  • website2/src/app/layout.tsx (2 hunks)
  • website2/src/app/robots.txt/route.ts (1 hunks)
  • website2/src/app/sitemap.xml/route.ts (1 hunks)
  • website2/src/components/GoogleAnalytics.tsx (1 hunks)
  • website2/src/components/layouts/NewsLetter.tsx (2 hunks)
  • website2/src/views/careers/CareerPage.tsx (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build-push-website2-deploy-preview
🔇 Additional comments (4)
website2/src/components/layouts/NewsLetter.tsx (3)

38-41: Nice improvement to error handling!

The error status is now consistently set in both the catch block and the else block, ensuring users always receive proper feedback.


70-125: Excellent responsive layout implementation!

The split layout for larger screens with proper spacing and alignment provides a better visual hierarchy and user experience. Good use of Tailwind's responsive classes.


127-152: Great feedback UI implementation!

The centered feedback states with emojis and clear messaging provide excellent user experience. Good job on accessibility with proper role and aria-label attributes.

website2/src/views/careers/CareerPage.tsx (1)

136-136: Excellent improvement to the no positions message!

The new message is more engaging and informative, providing better context while encouraging users to check back later. This aligns well with maintaining user engagement even when no positions are available.

Comment on lines +1 to +14
export async function GET() {
const robots = `
User-agent: *
Allow: /
Sitemap: https://airqo.net/sitemap.xml
`;

return new Response(robots, {
status: 200,
headers: {
'Content-Type': 'text/plain',
},
});
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Verify the hardcoded sitemap URL.

The implementation looks good, but let's ensure the hardcoded sitemap URL is correct and matches your production environment.


🏁 Script executed:

#!/bin/bash
# Description: Verify the sitemap URL is accessible
curl -I https://airqo.net/sitemap.xml

Length of output: 872


Action Required: Update the sitemap URL in the robots.txt route.

While the dynamic robots.txt implementation is correctly structured and follows Next.js conventions, our verification indicates that the sitemap URL ("https://airqo.net/sitemap.xml") returns a 404 error. This suggests that the URL might be incorrect or not yet deployed in the production environment.

  • Please verify the correct sitemap URL for your production setup.
  • Update the hardcoded URL in website2/src/app/robots.txt/route.ts accordingly.

Comment on lines +20 to +27
<Script id="ga-script" strategy="afterInteractive">
{`
window.dataLayer = window.dataLayer || [];
function gtag(){ dataLayer.push(arguments); }
gtag('js', new Date());
gtag('config', '${measurementId}');
`}
</Script>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider adding cookie consent check.

The GA initialization looks good, but consider checking for user consent before initializing tracking.

 <Script id="ga-script" strategy="afterInteractive">
   {`
     window.dataLayer = window.dataLayer || [];
     function gtag(){ dataLayer.push(arguments); }
     gtag('js', new Date());
+    // Only initialize GA if user has consented to tracking
+    if (localStorage.getItem('cookieConsent') === 'true') {
       gtag('config', '${measurementId}');
+    }
   `}
 </Script>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<Script id="ga-script" strategy="afterInteractive">
{`
window.dataLayer = window.dataLayer || [];
function gtag(){ dataLayer.push(arguments); }
gtag('js', new Date());
gtag('config', '${measurementId}');
`}
</Script>
<Script id="ga-script" strategy="afterInteractive">
{`
window.dataLayer = window.dataLayer || [];
function gtag(){ dataLayer.push(arguments); }
gtag('js', new Date());
// Only initialize GA if user has consented to tracking
if (localStorage.getItem('cookieConsent') === 'true') {
gtag('config', '${measurementId}');
}
`}
</Script>

Comment on lines +51 to +63
const urlsXml = staticRoutes
.map((route) => {
// Remove leading/trailing slashes, then create the full URL
const path = route.replace(/^\/|\/$/g, '');
return `
<url>
<loc>${baseUrl}/${path}</loc>
<lastmod>${new Date().toISOString().split('T')[0]}</lastmod>
<priority>0.80</priority>
</url>
`;
})
.join('');
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider adding dynamic routes to sitemap.

The static routes look good, but consider adding support for dynamic routes (e.g., blog posts, events).

 const urlsXml = staticRoutes
   .map((route) => {
     const path = route.replace(/^\/|\/$/g, '');
     return generateUrlEntry(baseUrl, path);
   })
+  .concat(await getDynamicRoutes())  // Add dynamic routes
   .join('');

+async function getDynamicRoutes() {
+  // Fetch dynamic routes from your CMS or database
+  // Example: blog posts, events, etc.
+  return [];
+}
+
+function generateUrlEntry(baseUrl: string, path: string) {
+  return `
+    <url>
+      <loc>${baseUrl}/${path}</loc>
+      <lastmod>${new Date().toISOString().split('T')[0]}</lastmod>
+      <priority>0.80</priority>
+    </url>
+  `;
+}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const urlsXml = staticRoutes
.map((route) => {
// Remove leading/trailing slashes, then create the full URL
const path = route.replace(/^\/|\/$/g, '');
return `
<url>
<loc>${baseUrl}/${path}</loc>
<lastmod>${new Date().toISOString().split('T')[0]}</lastmod>
<priority>0.80</priority>
</url>
`;
})
.join('');
const urlsXml = staticRoutes
.map((route) => {
const path = route.replace(/^\/|\/$/g, '');
return generateUrlEntry(baseUrl, path);
})
.concat(await getDynamicRoutes())
.join('');
async function getDynamicRoutes() {
// Fetch dynamic routes from your CMS or database
// Example: blog posts, events, etc.
return [];
}
function generateUrlEntry(baseUrl: string, path: string) {
return `
<url>
<loc>${baseUrl}/${path}</loc>
<lastmod>${new Date().toISOString().split('T')[0]}</lastmod>
<priority>0.80</priority>
</url>
`;
}

Copy link
Contributor

New Website2 changes available for preview here

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (4)
website2/src/views/solutions/AfricanCities/AfricanCities.tsx (2)

104-124: Great responsive design implementation with room for optimization.

The new grid layout with progressive enhancement for mobile is well thought out. Consider these optimizations:

  1. Add responsive image sizes to optimize downloads:
 <Image
   src={img.image_url}
   alt={`City Image ${img.id}`}
   width={500}
   height={500}
+  sizes="(max-width: 640px) 100vw, 50vw"
   className="rounded-lg shadow-md object-cover w-full h-full transition-transform duration-500 ease-in-out transform hover:scale-110 cursor-pointer"
 />
  1. Prevent layout shifts during hover:
-className="rounded-lg shadow-md object-cover w-full h-full transition-transform duration-500 ease-in-out transform hover:scale-110 cursor-pointer"
+className="rounded-lg shadow-md object-cover w-full h-full transition-transform duration-500 ease-in-out transform hover:scale-110 cursor-pointer will-change-transform"

125-134: Optimize the overlay blob image loading.

Since this is a decorative overlay, consider these performance optimizations:

 <Image
   src="https://res.cloudinary.com/dbibjvyhm/image/upload/v1728132435/website/photos/about_us_vector_3_p0mihk.png"
   alt="Blob Overlay"
   width={510}
   height={360}
+  loading="lazy"
+  priority={false}
   className="object-cover rounded-lg w-full h-full"
 />

Also, consider adding role="presentation" since this is a decorative element.

website2/src/views/solutions/communities/CommunityPage.tsx (2)

112-148: Consider optimizing image dimensions for performance.

The image section restructuring improves responsive behavior and accessibility with proper alt text. However, the increased image dimensions (500x500, 500x700) might impact page load performance.

Consider:

  1. Using Next.js's built-in image optimization features:
 <Image
   src="..."
   alt="Champion 2"
   width={500}
   height={500}
+  quality={75}
+  priority={false}
   className="rounded-lg object-cover w-full h-full"
 />
  1. Implementing lazy loading for images below the fold
  2. Using responsive image sizes:
 <Image
   src="..."
   alt="Champion 2"
   width={500}
   height={500}
+  sizes="(max-width: 640px) 100vw, 50vw"
   className="rounded-lg object-cover w-full h-full"
 />

Also applies to: 241-277


94-94: Use Tailwind's built-in text sizes for consistency.

Using exact pixel values (text-[32px]) for text sizes might lead to inconsistency across the application. Tailwind provides predefined text sizes that maintain a consistent type scale.

Consider using Tailwind's built-in text sizes:

-<h2 className="text-[32px] leading-[36px] font-medium">
+<h2 className="text-4xl leading-tight font-medium">
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f216525 and fcc2744.

📒 Files selected for processing (3)
  • website2/.env.sample (1 hunks)
  • website2/src/views/solutions/AfricanCities/AfricanCities.tsx (2 hunks)
  • website2/src/views/solutions/communities/CommunityPage.tsx (5 hunks)
✅ Files skipped from review due to trivial changes (1)
  • website2/.env.sample
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build-push-website2-deploy-preview
🔇 Additional comments (2)
website2/src/views/solutions/AfricanCities/AfricanCities.tsx (1)

38-38: Nice improvement on the early return!

Explicitly returning null instead of an implicit undefined follows React best practices and improves type safety.

website2/src/views/solutions/communities/CommunityPage.tsx (1)

81-81:

❓ Verification inconclusive

Verify layout breakpoints on various screen sizes.

Changing from lg:grid-cols-2 to sm:grid-cols-2 triggers the two-column layout on smaller screens (640px) instead of larger screens (1024px). This might cause content to feel cramped on tablets and smaller laptops.

Consider testing the layout on various devices to ensure optimal content presentation:

Also applies to: 218-218


🏁 Script executed:

#!/bin/bash
# Description: Search for similar grid breakpoint patterns in the codebase
# to ensure consistency in responsive design approach

# Search for grid-cols-2 usage with breakpoints
rg "grid-cols-\d+\s+\w+:grid-cols-2" --type tsx

Length of output: 77


Verify layout breakpoints on various screen sizes.

Changing from lg:grid-cols-2 to sm:grid-cols-2 activates the two-column layout at 640px instead of 1024px. This change may cause content to appear cramped on tablets and smaller laptops. Since our initial script returned an error due to the unrecognized file type "tsx", please manually verify the responsive behavior across devices. Consider testing the layout to ensure optimal presentation and consistency with other grid implementations.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants