Server-to-Server (S2S) API Integration Guide
Date Published
- Twitter
- Facebook
- LinkedIn
- Instagram
- Copy Link

GLP Winner Affiliate Tracking: Server-to-Server (S2S) API Integration Guide
This method is recommended for providers with backend development capabilities.
Overview
The S2S integration involves your server sending a direct HTTP POST request to GLP Winner's /api/track/v1/conversion endpoint when a conversion event occurs (e.g., a patient sign-up or purchase originating from an affiliate referral).
Your server is responsible for:
- Capturing the glp_click_id from the landing page URL when a user arrives via an affiliate link.
- Storing this glp_click_id (e.g., in the user's session, your database, or passing it through your application flow).
- When a conversion happens, sending this glp_click_id along with other required details to the GLP Winner conversion API endpoint.
API Endpoint Details
Record Conversion
- Method: POST
- URL:
1https://www.glpwinner.com/api/track/v1/conversion
- Headers:
1 Content-Type: application/json2 Authorization: Bearer <YOUR_API_TOKEN> (Replace <YOUR_API_TOKEN> with the unique API token provided to you by GLP Winner.)
- Request Body (JSON):
1 {2 "providerId": 123,3 "transaction_id": "CLICK_ID_FROM_URL_PARAM",4 "email": "user@example.com",5 "ip": "123.45.67.89",6 "conversion_id": "YOUR_INTERNAL_ORDER_ID_OR_USER_ID"7 }
Field Descriptions:
providerId (number, required)
Your unique numeric Provider ID assigned by GLP Winner (this corresponds to your ID in the main GLP Winner system, not the tracking system's internal UUID).
transaction_id (string, required)
The glp_click_id captured from the affiliate link URL query parameter. This is the primary identifier for the affiliate click.
email (string, optional)
The email address of the converting user. Recommended for soft-matching if transaction_id is unexpectedly lost.
ip (string, optional)
The IP address of the converting user. Recommended for soft-matching. Ensure this is the end-user's IP, not your server's IP.
conversion_id (string, optional)
Your internal unique identifier for this conversion (e.g., order ID, subscription ID, user ID). Useful for reconciliation and invoicing.
Note: While transaction_id is marked as "Yes" for S2S, the API technically requires either transaction_id or session_token. For S2S, transaction_id is the standard.
Behavior with New transaction_id (Inferred Clicks): If you provide a transaction_id (i.e., glp_click_id) that GLP Winner's system has not logged before for your provider account, our system will create an "inferred" click record in our track_clicks table. This new record will use the transaction_id you sent, associate it with your provider account, and capture details like the IP address from your server's request. The conversion will then be attributed to this newly inferred click. This mechanism ensures maximum attribution, assuming the glp_click_id you send is a valid one originating from your affiliate program.
Soft-Matching for S2S: If you are unable to provide a transaction_id for a conversion (e.g., it was lost), you can omit it and instead provide email and/or ip in the payload. Our system will attempt to find a recent, unconverted click associated with your provider account that matches the provided email or IP. The track_clicks table (which is searched for soft matches) is populated by:
- Clicks logged via the client-side JavaScript SDK (if you also use it on your frontend, these calls populate IP and potentially email).
- Inferred clicks created from previous S2S conversion calls that did include a transaction_id (these will have IP data). If a soft match is successful, the conversion will be attributed. If not, a 422 Unprocessable Entity error is returned. For best soft-match results with S2S, ensure any available user IP is passed in the ip field of the conversion payload.
Authentication
Authentication is performed using a Bearer token in the Authorization header. You will receive your unique API_TOKEN from GLP Winner. Keep this token secure on your server.
Response Codes
201 Created: Conversion successfully recorded.
1 {2 "status": "ok",3 "message": "Conversion recorded successfully.",4 "conversion_id": "internal_conversion_uuid", // GLP Winner's internal ID for this conversion5 "glp_click_id": "CLICK_ID_FROM_URL_PARAM",6 "recorded_at": "timestamp"7 }
200 OK (with status: "duplicate"): Conversion was already recorded for this transaction_id. No new conversion logged.
1 {2 "status": "duplicate",3 "message": "Conversion already tracked for this click.",4 "conversion_id": "internal_uuid_of_original_conversion"5 }
400 Bad Request: Invalid request body or missing required fields. The response body may contain details.
1 {2 "error": "Invalid request body",3 "details": { /* Zod error formatting */ }4 }
401 Unauthorized: API token missing or not presented correctly.
1 { "error": "Unauthorized: API token missing." }
403 Forbidden: Invalid API token or provider ID mismatch.
1 { "error": "Unauthorized: Invalid API token." }
422 Unprocessable Entity: Conversion could not be attributed (e.g., transaction_id not found and soft-matching failed).
1 { "error": "Conversion not attributed: No valid click identifier found or matched." }
500 Internal Server Error: An error occurred on GLP Winner's server.
1 { "error": "Internal Server Error" }
Example cURL Request
1curl -X POST https://www.glpwinner.com/api/track/v1/conversion \2 -H "Authorization: Bearer YOUR_API_TOKEN" \3 -H "Content-Type: application/json" \4 -d '{5 "providerId": 123,6 "transaction_id": "affiliateClickId12345",7 "email": "new.patient@example.com",8 "ip": "203.0.113.45",9 "conversion_id": "ORDER-ABC-789"10 }'
Example Fetch API Example (Node.js)
1async function recordConversionAsync() {2 const apiUrl = 'https://www.glpwinner.com/api/track/v1/conversion';3 const apiToken = 'YOUR_API_TOKEN'; // Replace with your actual API token45 // Replace with your actual data6 const payload = {7 providerId: 123,8 transaction_id: 'affiliateClickId12345',9 email: 'new.patient@example.com',10 ip: '203.0.113.45',11 conversion_id: 'ORDER-ABC-789',12 };1314 try {15 const response = await fetch(apiUrl, {16 method: 'POST',17 headers: {18 'Content-Type': 'application/json',19 'Authorization': `Bearer ${apiToken}`,20 },21 body: JSON.stringify(payload),22 });2324 const responseData = await response.json();2526 if (response.ok) { // status in the range 200-29927 console.log('Conversion recorded successfully (Fetch):', responseData);28 // responseData will contain:29 // {30 // "status": "ok", // or "duplicate" if 200 OK31 // "message": "Conversion recorded successfully.", // or "Conversion already tracked..."32 // "conversion_id": "internal_conversion_uuid",33 // "glp_click_id": "affiliateClickId12345", // if applicable34 // "recorded_at": "timestamp" // if applicable35 // }36 } else {37 console.error('Error recording conversion (Fetch):', response.status, responseData);38 // Handle specific error codes (400, 401, 403, 422, 500)39 // responseData might contain:40 // { "error": "Error message", "details": { ... } }41 }42 } catch (error) {43 console.error('Network or other error (Fetch):', error.message);44 }45}4647// Example usage:48// recordConversionAsync();49
Example Axios API Example (Node.js)
1import axios from 'axios';23async function recordConversionAsync() {4 const apiUrl = 'https://www.glpwinner.com/api/track/v1/conversion';5 const apiToken = 'YOUR_API_TOKEN'; // Replace with your actual API token67 // Replace with your actual data8 const payload = {9 providerId: 123,10 transaction_id: 'affiliateClickId12345',11 email: 'new.patient@example.com',12 ip: '203.0.113.45',13 conversion_id: 'ORDER-ABC-789',14 };1516 try {17 const response = await axios.post(apiUrl, payload, {18 headers: {19 'Content-Type': 'application/json',20 'Authorization': `Bearer ${apiToken}`,21 },22 });2324 console.log('Conversion recorded successfully (Axios):', response.data);25 // Handle successful response (e.g., response.status === 201 for created, or 200 for duplicate)26 // response.data will contain:27 // {28 // "status": "ok", // or "duplicate"29 // "message": "Conversion recorded successfully.", // or "Conversion already tracked..."30 // "conversion_id": "internal_conversion_uuid",31 // "glp_click_id": "affiliateClickId12345", // if applicable32 // "recorded_at": "timestamp" // if applicable33 // }34 } catch (error) {35 if (error.response) {36 // The request was made and the server responded with a status code37 // that falls out of the range of 2xx38 console.error('Error recording conversion (Axios):', error.response.status, error.response.data);39 // Handle specific error codes (400, 401, 403, 422, 500)40 // error.response.data might contain:41 // { "error": "Error message", "details": { ... } }42 } else if (error.request) {43 // The request was made but no response was received44 console.error('Error: No response received (Axios)', error.request);45 } else {46 // Something happened in setting up the request that triggered an Error47 console.error('Error setting up request (Axios):', error.message);48 }49 }50}5152// Example usage:53// recordConversionAsync();54
Example Hybrid Client Side & s2s:
Add glp.js script and <GLPInit /> from client side doc. Initialize with useSession: false so we store raw glp_click_id.
Now read from cookie on client side confirmation:
1 const handleSubmit = async () => {2 // Helper function to get a cookie by name3 const getCookie = (name: string): string | null => {4 const nameEQ = name + "=";5 const ca = document.cookie.split(';');6 for(let i = 0; i < ca.length; i++) {7 let c = ca[i];8 while (c.charAt(0) === ' ') c = c.substring(1, c.length);9 if (c.indexOf(nameEQ) === 0) return c.substring(nameEQ.length, c.length);10 }11 return null;12 };1314 const glpClickId = getCookie('_glp_cid'); // Default cookie name for glp_click_id with1516 if (!glpClickId) {17 console.warn('GLP Click ID cookie (_glp_cid) not found for Semaglutide page. S2S conversion might rely on soft-matching.');18 }1920 const s2sApiPayload = {21 glpClickId: glpClickId, // Can be null if not found22 email: formData.email,23 };2425 try {26 // Your server code will actually make the postback to our GLP Winner servers.27 const response = await fetch('/api/glp-s2s-conversion', {28 method: 'POST',29 headers: {30 'Content-Type': 'application/json',31 },32 body: JSON.stringify(s2sApiPayload),33 });3435 const result = await response.json();36 if (response.ok) {37 console.log('S2S conversion request processed by internal API:', result);38 } else {39 console.error('Internal API error for S2S conversion:', result);40 }41 } catch (error) {42 console.error('Network error during S2S conversion request:', error);43 } finally {44 // Navigate to confirmation page regardless of S2S outcome for now45 window.location.href = '/confirmation';46 }47 };
Best Practices
- Secure Your API Token: Store your API token securely on your server. Do not expose it in client-side code.
- Capture glp_click_id Reliably: Ensure your system correctly captures and persists the glp_click_id from the initial user landing.
- Timely Reporting: Send the conversion event to GLP Winner as soon as the conversion is confirmed on your end.
- Error Handling: Implement retry logic for transient errors (e.g., network issues, 5xx server errors from GLP Winner). However, do not retry indefinitely for client errors (4xx).
- Pass Optional Data: Providing email, ip, and conversion_id is recommended as it aids in potential soft-matching (if the transaction_id is somehow lost) and data reconciliation.
Testing
Using Test Mode: To ensure your production data remains clean during testing, you can make API calls in "test mode". This will flag the generated click and conversion data as test data in GLP Winner's system, allowing it to be filtered or periodically purged.
To use test mode, append the query parameter ?testMode=true to the API endpoint URL. For example:
1https://www.glpwinner.com/api/track/v1/conversion?testMode=true
The API will process the request using your real credentials but mark the resulting data as test data. The API response may also include a mode: "test" field to confirm this.
General Test Steps: You can test your integration by:
- Simulating an affiliate click by accessing your website with a test glp_click_id (e.g., https://yourwebsite.com/?glp_click_id=testClick123).
- Storing this testClick123.
- Triggering a conversion event in your system for this user session.
- Ensuring your server sends the correct payload to the GLP Winner /api/track/v1/conversion endpoint.
For questions or support, please email us.
Keep Reading
Curated by
