Data collection
Learn how to collect information for personalization.
This guide provides practical examples of using the Hydrogen SDK to enrich user profiles and sessions with information relevant to your business.
User data
You can persist user-related information in one of the two ways described below depending on whether it is related to the user’s profile or their current session.
Profile data
You can enrich user profiles with details collected via forms, surveys, or other means.
These pieces of information, called attributes, are categorized as standard or custom depending on whether it is generic or specific to your organization.
Standard attributes
These are predefined attributes that are common most businesses, such as the user’s name, email, and interests.
You can set standard attributes using the user.edit method. For example, let’s say you have a newsletter subscription form, and you want to add the email address to the user profile on Croct.
This is what it would look like:
import type {FormEvent} from 'react';import {useCroct} from '@croct/plug-hydrogen';
export function NewsletterForm() {const croct = useCroct();const subscribe = event => { const form = new FormData(event.currentTarget); const email = form.get('email');
// Your logic to persist the email api.subscribe(email);
croct.user.edit() .set('email', email) .save();};
return ( <form onSubmit={subscribe}> 📫 Subscribe to our newsletter! <input type="email" placeholder="Email"/> <button type="submit">Subscribe</button> </form>);}The user.edit method returns a Patch instance that allows you to chain multiple operations together.
You could alternatively write:
const patch = croct.user.edit();patch.set('email', email);
await patch.save();When you call save, it saves changes to the user profile and returns a promise that confirms the operation.
You can then access standard attributes in your queries using the user variable:
user's email ends with "@croct.com"For a complete list of attributes, see User profile reference.
Custom attributes
In addition to the standard attributes, you can add custom attributes to enrich user profiles with information relevant to your business.
For example, let’s say you have a SaaS application and you want to ask your users about their area of expertise so you can personalize the onboarding experience.
This is what it would look like:
import {useCroct} from '@croct/plug-hydrogen';
export function ExpertiseSelector() {const croct = useCroct();
const onChange = event => { croct.user.edit() .set('custom.expertise', event.target.value) .save();};
return ( <select onChange={onChange}> <option value="Engineering">Engineering</option> <option value="Design">Design</option> <option value="Marketing">Marketing</option> </select>);}Note that custom attributes are prefixed with custom to avoid conflicts with standard attributes. However, you do not need to include the prefix in your queries:
user's expertise is "Engineering"Session data
Besides user profiles, you can also store information relevant to the user’s current session.
Storing session information can help you keep track of important the user’s current session that may not be relevant to their profile. For example, you can store the plan the user selected on the pricing page, or any other information you want to record during the user’s visit.
To store session information, use the session.edit method:
import {useCroct} from '@croct/plug-hydrogen';
export function PlanCard({plan, price}) {const croct = useCroct();
const onSelect = () => { croct.session.edit() .set('plan', plan) .save();};
return ( <div> <strong>{plan}</strong> <p>${price}</p> <button onClick={onSelect}>Select</button> </div>);}In the same way as with user profiles, the session.edit method returns a Patch instance that allows you to chain multiple operations together.
const patch = croct.session.edit();patch.set('plan', plan);
await patch.save();When you call save, it saves changes to the session and returns a promise that confirms the operation. You can then access session information in your queries using the session variable:
session's plan is "premium"For a complete list of attributes, see Session reference.
User identity
By default, all visitors are anonymous, recognized across requests by a client ID. If your storefront has logged-in customers, you can link the Croct user profile with their Shopify customer ID so that personalization stays consistent across devices and sessions.
Automatic handling
When your storefront uses Shopify customer accounts, the logged-in customer is identified on every request out of the box, reading the customer ID from the Customer Account API. No extra code is required.
The default behavior relies on the Customer Account API session, so visitors authenticated another way are not visible to it. To support them, provide your own identity resolver, which reads the identity from your own source. This covers guest-only stores, the classic customer accounts on the Storefront API, and your own or third-party authentication such as Auth0, SSO, or a custom backend. Return the logged-in user’s ID, or nothing to keep the visitor anonymous.
Provide the resolver to the middleware on React Router 7, or to the context helper on Remix:
import {createCroctMiddleware} from '@croct/plug-hydrogen/server';
export const middleware = [ createCroctMiddleware({ // Return the logged-in user ID from your own auth, or null when anonymous. userIdResolver: context => resolveUserId(context), }),];For a guest-only storefront, the resolver can return nothing so that every visitor stays anonymous.
Manual handling
To control identity within a request, use the identify and anonymize functions from a loader or action.
The following example identifies a customer when they log in:
import {redirect} from 'react-router';import {identify} from '@croct/plug-hydrogen/server';import type {Route} from './+types/login';
export async function action({request, context}: Route.ActionArgs) { const form = await request.formData();
await identify(String(form.get('customerId')), context);
return redirect('/account');}Anonymize the visitor after logout in the same way:
import {redirect} from 'react-router';import {anonymize} from '@croct/plug-hydrogen/server';import type {Route} from './+types/logout';
export async function action({context}: Route.ActionArgs) { await anonymize(context);
return redirect('/');}