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

Improve demo store SEO & ld+json implementation #598

Closed

Conversation

juanpprieto
Copy link
Contributor

@juanpprieto juanpprieto commented Feb 28, 2023

WHY are these changes introduced?

Fixes first task of #593

TODO:

  • Add collection seo + ldJson
  • Add journal/blog seo + ldJson
  • Add pages seo + ldJson

WHAT is this pull request doing?

Done

  • Moved root.tsx seo to loader pattern and added Organization ldJson
  • added ldJson to products/$productHandle based on Dawn Theme.
  • added a couple of wip analyticsPayload and seoPayload helpers to both templates to make them improve the DX and cosistency.

Issues:

  • ldJson currently does not allow for multiple tags to be defined at root and route level. This is a pattern in Dawn so we might need to change the ldJson API to allow for this. We are discussing with Paul Shapiro.

Suggestion:

Instead of having a hook useAnalytics should we instead have a <Analytics /> component to better align with the Seo component and remix's own Script, Head etc...

Change this

export default function App() {
  const data = useLoaderData<typeof loader>();
  const locale = data.selectedLocale ?? DEFAULT_LOCALE;
  const hasUserConsent = true;

  useAnalytics(hasUserConsent, locale);

  return (
    <html lang={locale.language}>
      <head>
        <Seo />
        <Meta />
        <Links />
      </head>
      <body>
        <Layout
          layout={data.layout as LayoutData}
          key={`${locale.language}-${locale.country}`}
        >
          <Outlet />
        </Layout>
        <ScrollRestoration />
        <Scripts />
      </body>
    </html>
  );
}

to

export default function App() {
  const data = useLoaderData<typeof loader>();
  const locale = data.selectedLocale ?? DEFAULT_LOCALE;
  const hasUserConsent = true;

  return (
    <html lang={locale.language}>
      <head>
        <Seo />
        <Meta />
        <Links />
      </head>
      <body>
        <Layout
          layout={data.layout as LayoutData}
          key={`${locale.language}-${locale.country}`}
        >
          <Outlet />
        </Layout>
        <ScrollRestoration />
        <Analytics userConsent={hasUserConsent} locale={locale} />
        <Scripts />
      </body>
    </html>
  );
}

HOW to test your changes?

Post-merge steps

Checklist

  • I've read the Contributing Guidelines
  • I've considered possible cross-platform impacts (Mac, Linux, Windows)
  • I've added a changeset if this PR contains user-facing or noteworthy changes
  • I've added tests to cover my changes

@wizardlyhel
Copy link
Contributor

I'm good with the analyticPayload clean up but to convert useAnalytics hook to a component only for consistency is weird. useAnalytics hook doesn't need to render anything.

@blittle
Copy link
Contributor

blittle commented Feb 28, 2023

I'm good with the analyticPayload clean up but to convert useAnalytics hook to a component only for consistency is weird. useAnalytics hook doesn't need to render anything.

A component doesn't need to render anything. There's a lot of precedence in the React ecosystem to have components that don't render. I think the bigger question is the dev ergonomics. Do we ever expect useAnalytics to return some sort of data? If it's a component, then you gotta use render props to pass data out. Pros and cons to both.

@juanpprieto
Copy link
Contributor Author

juanpprieto commented Feb 28, 2023

I agree. From a DX perspective it feels much more love-letter-to-remix to have both <Analytics /> and <Seo /> as components.

<Analytics /> would just be a simple wrapper for useAnalytics after all similar to how useFetcher.form wraps Form under the hood.

@frehner
Copy link
Contributor

frehner commented Feb 28, 2023

Slight preference on the "custom hook" form over a "component that wraps a custom hook" form, but it's not strongly held. I don't see the need to make a component that does nothing, when custom hooks are a React ecosystem thing as well (and are also widely used).

@blittle
Copy link
Contributor

blittle commented Feb 28, 2023

I think my preference also leans towards the hook, because I totally imagine that the hook could return something, and I think it's easier to adapt.

benjaminsehl
benjaminsehl approved these changes Feb 28, 2023
@benjaminsehl benjaminsehl self-requested a review February 28, 2023 21:51
Copy link
Member

@benjaminsehl benjaminsehl left a comment

Choose a reason for hiding this comment

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

Edit: Approved by accident, meant to comment — since this is WIP and didn't top hat, can't approve.


If deleting the component is a shortcut to removing analytics reporting full stop -- that is kind of a nice escape hatch in an exploration of HIPAA compliance.

I don't feel really strongly either way; but I do think consistency of ergonomic is a good principle to follow -- so long as it doesn't compromise the overall DX or performance.

Likewise -- consistency here might mean we move to create a "useSeo" hook in hydrogen-react instead of a component for Analytics -- it might also mean that we say "we will consistently use components when we return markup, hooks when we don't".

I still have to dig through the SEO proposals but I'd say we should separate the two ideas -- don't necessarily shoot down the Analytics component idea, but don't commit to merging yet either. Just let it simmer for a bit and get some dogfooding in to see how it feels.


On the SEO stuff… 

This DX is so much cleaner and easier to follow -- love this direction.

Also, glad you're using Brand Settings API. We should push to see if they can expand what's exposed to include all of the social links, etc. so we can make OG defaults use Brand as the source of truth. Makes it a really nice clean place to edit a single screen and have your full app get up to date.

Copy link
Contributor

@cartogram cartogram left a comment

Choose a reason for hiding this comment

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

🚀 @juanpprieto Thank you for helping with this!

I actually like the component that renders nothing pattern.... makes it easy to be consistent (you can move a hook into a component, but its awkward/sometimes impossible to go the the other way). So @benjaminsehl we can't do the useSeo hook because we produce markup (we could explore this limitation more though).

I think there has always been a good amount of sharing between seo and analytics in trying to come up with consistent APIs. Its great to see that continue to play out here ❤️

primaryDomain {
url
}
brand {
Copy link
Contributor

@cartogram cartogram Feb 28, 2023

Choose a reason for hiding this comment

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

Future thing: If we move the helpers into the hydrogen-react package (they not are tied to remix/framework agnostic) we should warn and provide lint rules for missing request data. It's easy to miss and prone to confusion, but I don't think its a dealbreaker here since we rely on this pattern all the time. If anything, this will further encourage us to provide some DX to bridge the "I am using this thing" and "I need to add xyz fields to the query".

};
}

function seoPayload({
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: I think add the word product to these ones. ie: seoProductPayload or getProductSeo, but not interested in bikeshedding names at this point.

Copy link
Member

Choose a reason for hiding this comment

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

I think it's worth bikeshedding! Less about this specific one and more for the precedent of the pattern overall.

From a design elegance POV -- I like that it's a single function; maybe could accept an arg for the resource type.

However -- I'm being naive about in that suggestion? Is there a reason to be more imperative w/ function names? Like would it be a lot more prone to getting things wrong or something?

Copy link
Contributor Author

@juanpprieto juanpprieto Feb 28, 2023

Choose a reason for hiding this comment

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

Cool, I was thinking of maybe moving these utils to a seo/ and analytics/ folders inside the demo store. I'm easy with bikeshedding their names, but not sure these should ever move to hydrogen as they are very project-specific.

@frehner
Copy link
Contributor

frehner commented Feb 28, 2023

So @benjaminsehl we can't do the useSeo hook because we produce markup (we could explore this limitation more though).

Can you clarify this? Are you producing JSX or are you producing something else? (I was under the impression that you were producing something else and then turning it into JSX, but I could be wrong. Maybe that's only the hydrogen-react one that I'm thinking about?)

@cartogram
Copy link
Contributor

cartogram commented Feb 28, 2023

Can you clarify this? Are you producing JSX or are you producing something else? (I was under the impression that you were producing something else and then turning it into JSX, but I could be wrong. Maybe that's only the hydrogen-react one that I'm thinking about?)

Exactly. The component still returns JSX (its the react/remix bridge). The part that returns the abstract dom objects are the hydrogen-react part.

frandiox and others added 3 commits February 28, 2023 16:27
migrate analytic payloads helpers to lib/analytics

seo + analytics demo store implementation

cleanup analytics refactor
@juanpprieto juanpprieto changed the title WIP: Extend demo store SEO implementation Improve demo store SEO & ld+json implementation Mar 7, 2023
@juanpprieto
Copy link
Contributor Author

Moved to #651

@juanpprieto juanpprieto closed this Mar 7, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants