Skip to main content

Common Phases: Discovery & Valuation

These phases are required for all integrations, regardless of which payment path you choose.


Understanding Sessions

Before implementing, understand how session management works between your system and Ealyx.

Session Flow Diagram

Terminology

TermWhat it isWho generates it
Your session_idYour internal session identifier (PHP session, JWT, cookie, etc.)Your backend
saltA secret key for HMAC generation (store securely, never expose)Your backend
session_hash / session_hash_tokenHMAC-SHA256 hash of your session_id using salt as keyYour backend
Ealyx session_idEalyx's internal identifier for the valuation sessionEalyx API

Note: session_hash and session_hash_token refer to the same value. The _token suffix is used in the shopper_data response to emphasize it's a secure token.

Why HMAC-SHA256?

The session hash serves two security purposes:

  1. Privacy: Your real session_id is never exposed to Ealyx or the browser
  2. Integrity: HMAC (vs simple hash) provides timing-attack resistance
❌ WRONG: SHA256(session_id + salt)     → vulnerable to length extension attacks
✅ RIGHT: HMAC-SHA256(session_id, salt) → cryptographically secure

Session Redirect

When you call GET /core/sessions/{session_hash}, Ealyx may return a session_id different from your hash. This happens when:

  • The session was updated server-side (e.g., customer linked accounts)
  • Multiple valuations were consolidated

How to handle it:

1. Call GET /core/sessions/{your_session_hash}
2. If response.session_id ≠ your_session_hash:
→ Retry: GET /core/sessions/{response.session_id}
(Use the returned session_id directly - no re-hashing needed)
3. Use the tradein_item from the final response

Note: The session_id returned by Ealyx is their internal identifier. When doing a redirect, use it directly as the path parameter without applying HMAC.


Phase 1: Discovery - Display Teasers

Flow Diagram:

Implementation:

Add teaser placeholders across your site:

<!-- Homepage banner -->
<div class="ealyx-teaser" data-type="banner"></div>

<!-- Product detail page -->
<div class="ealyx-teaser" data-type="product-widget"></div>

<!-- Cart page (both types) -->
<div class="ealyx-teaser" data-type="product-widget"></div>
<div class="ealyx-teaser" data-type="cart-summary"></div>

<!-- Checkout page -->
<div class="ealyx-teaser" data-type="cart-summary"></div>

<!-- Thank you page -->
<div class="ealyx-teaser" data-type="thank-you"></div>

Note: For advanced teaser placement strategies, see Advanced Features


Phase 2: Valuation & Identification

Flow Diagram:

When customers click "Calculate Discount", the valuation wizard opens in a modal window (iframe). If the shopper accepts the offer, the selected product and discount details are automatically reflected in the corresponding widget(s).

In case the shopper leaves the site without completing a purchase, the valuation can be used to try to reactivate the shopper. To enable this, the Ealyx frontend script will request shopper data from your backend system.

Implement Shopper Data Endpoint

Create a GET endpoint at $MERCHANT_CALLBACKS_BASE/shopper_data on your backend. This endpoint returns customer session information and a session hash token.

Who calls this endpoint: The Ealyx frontend SDK (running in the customer's browser in same domain of web) calls this endpoint via JavaScript AJAX when the valuation modal needs customer data.

Endpoint Specification:

GET $MERCHANT_CALLBACKS_BASE/shopper_data

Response Format:

Your endpoint must return JSON with this structure:

{
"customer": {
"id": "customer_123",
"email": "john@example.com",
"given_name": "John",
"family_name": "Doe"
},
"session_hash_token": "sha256_hash_of_session_with_salt"
}

Note: The customer object includes only: id, email, given_name, family_name. These fields are required when the customer is logged in. For guest checkout, set customer and session_hash_token to null.

Session Hash Token Generation:

The session hash is a secure token derived from your session ID using HMAC-SHA256. It should:

  • Never expose your real session ID
  • Use a random salt as the HMAC key for security
  • Be deterministic (same input = same output)
  • Use HMAC-SHA256 (timing-attack resistant)

Example implementation:

# Generate session hash using HMAC-SHA256
session_id="abc123def456"
salt="your_random_salt_16plus_bytes"

# Using openssl (recommended)
session_hash=$(echo -n "$session_id" | openssl dgst -sha256 -hmac "$salt" | cut -d' ' -f2)
# Result: "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"

# Alternative using printf (if openssl dgst doesn't support -hmac on your system)
# session_hash=$(printf '%s' "$session_id" | openssl dgst -sha256 -hmac "$salt" -hex | cut -d' ' -f2)

⚠️ IMPORTANT: Use HMAC-SHA256 as shown above, NOT simple SHA256 hash. The salt must be treated as the HMAC secret key, not concatenated with the session_id. This provides timing-attack resistance.

Example Implementation (Pseudocode):

Create an endpoint that retrieves customer data from your session, and returns it in JSON format:

# Pseudocode - adapt to your language/framework

# Get session ID from your session management system
session_id = get_session_id()

# Get customer data from your database (if logged in)
customer_data = None
session_hash = None
if session_id and is_logged_in():
customer = get_customer_from_database()
customer_data = {
'id': customer.id,
'email': customer.email,
'given_name': customer.first_name,
'family_name': customer.last_name
# Note: phone field is NOT part of customer object, only id/email/given_name/family_name
}
# Generate session hash using HMAC-SHA256
salt = 'your_session_salt_key' # Store this in your session/database
session_hash = HMAC_SHA256(session_id, salt)
else:
# For guest checkout, return null
customer_data = None

# Return JSON response
return {
'customer': customer_data,
'session_hash_token': session_hash
}

⚠️ Note on Guest Checkout: If customer is null, Ealyx will display trade-in options linked to a temporary session. Once the customer logs in, the trade-in data is migrated to their merchant session. This behavior is intentional — customers must be identified to complete a trade-in and apply the discount.

Testing with curl:

curl -X GET '$MERCHANT_CALLBACKS_BASE/shopper_data' \
-H 'Content-Type: application/json' \
-b 'Cookie-Session: $SESSION'

# Response:
# {
# "customer": {
# "id": "customer_123",
# "email": "john@example.com",
# "given_name": "John",
# "family_name": "Doe"
# },
# "session_hash_token": "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"
# }

What to Store:

For each session, persist these fields:

  • session_id - Your internal session identifier (for regeneration with hash and salt)
  • customer_id (optional) - Link to customer record

Key Principles:

  • Persistence required: You must store the hash to verify it later
  • Deterministic verification: Always regenerate from stored values
  • Auto-expiration: Automatically cleanup old sessions (24 hours is safe)
  • Timing-attack safe: Use constant-time string comparison when verifying
✓ Verification

Test your endpoint:

curl -X GET "$MERCHANT_CALLBACKS_BASE/shopper_data" \
-H 'Content-Type: application/json' \
-b 'session=YOUR_SESSION_COOKIE'
CheckExpectedIf it fails
HTTP status200 OKCheck endpoint URL and method (must be GET)
customer object{id, email, given_name, family_name}Ensure user is logged in
session_hash_tokenNon-null stringCheck HMAC-SHA256 implementation
Guest checkout{"customer": null, "session_hash_token": null}This is correct for guests