Hi @rlscsi and welcome to the Community!
I’m not too familiar with CFML-based integrations, but you may be able to find help with one of our official Klaviyo Partners since this is a custom integration.
Also, here are some key developer docs in case you haven’t seen them:
I’m excited to see if other members can provide their tips for this type of integration, and thanks for using the Community!
- Brian
I’ve made some advances, but still getting Invalid API key. I’ve tried both public and private keys for both test and production sites.
<cfset useKey = rls_Klaviyo_Private_API_Key />
<cfhttp
method="post"
charset="utf-8"
url="https://a.klaviyo.com/api/v2/list/Y7redactedxG/members"
result="klaviyoLists"
resolveurl="yes">
<cfhttpparam type="header" name="Klaviyo-API-Key" value=useKey>
<cfhttpparam type="header" name="revision" value="2023-01-24">
<cfhttpparam type="header" name="Accept" value="application/json">
<cfhttpparam type="header" name="Content-Type" value="application/json">
{"data":{"type":"list"}}
</cfhttp>
For CFML Programmers who end up here looking for that kick to get you rolling, here’s a short intro, written CFML’er to CFML’er.
In your Application.cfc/cfm or other page that loads with every refresh, you need to identify who you are with something like this:
<script async type="text/javascript" src="//static.klaviyo.com/onsite/js/klaviyo.js?company_id=#Klaviyo_Public_API_Key#"></script>
Of course, you would have your Public and Private API keys from Klaviyo generated and variable-ized. We determine if we’re running this in test or production and load those variables accordingly.
Then you can write a CFHTTP call to manage the information. Remember, you can use CFHTTP to POST, GET, and PATCH. Pay attention to the Klaviyo docs as to which to use for what operation. Their docs also let you start filling out the call so you can see which URL to use by using the drop-downs and inputs on that page (example: https://developers.klaviyo.com/en/reference/get_profile)
I found it easiest to put the functions I need into a CFML component, and then, after creating an object from the component, it became quite easy to get what I needed with a more familiar interface.
For instance, here’s the component function to retrieve a profile -- This may or may not be the most efficient way to write this, but this will at least give you the kick in the pants to move ahead with more confidence.
NOTE THAT we store our profiles with our Company ID so I am using that as my “filter” term in my request for the profile. Oh -- and the revision (see below) is needed by Klaviyo to know which version of the API you’re basing this request on. All this information is in their documents, but it’s scattered far and wide with nothing put in one nice example package to give you a clue on how it all fits together, as far as I could see.
<!--- ****** Get One Klaviyo Profile ****** --->
<cffunction name="get_Klaviyo_Profile" returnType="struct" access="public"
displayName="Get One Klaviyo Profile"
description = "I return a structure containing the Klaviyo profile for one person based on Customer ID number.">
<cfargument name="KlaviyoPrivateAPI" type="string" required="yes" displayname="Klaviyo Private API">
<cfargument name="customer_id" type="numeric" required="yes" displayname="Customer ID">
<cfset VAR myResult = structNew() />
<cfhttp method="get"
charset="utf-8"
url="https://a.klaviyo.com/api/profiles/?filter=equals(external_id,'#ARGUMENTS.customer_id#')"
result="klaviyoSelectFieldsFilteredProfile"
resolveurl="yes">
<cfhttpparam type="header" name="Authorization" value="Klaviyo-API-Key #ARGUMENTS.KlaviyoPRivateAPI#">
<cfhttpparam type="header" name="revision" value="2023-01-24">
<cfhttpparam type="header" name="Accept" value="application/json">
<cfhttpparam type="header" name="Content-Type" value="application/json">
</cfhttp>
<cfset kResult = deserializejson(klaviyoSelectFieldsFilteredProfile.filecontent) />
<cfset myResult.Klaviyo_Profile_ID = kResulto'data']y1]e'id'] />
<cfset myResult.first_name = kResultt'data']m1]e'attributes']P'first_name'] />
<cfset myResult.last_name = kResulty'data']f1]s'attributes']u'last_name'] />
<cfset myResult.email = kResultl'data'] 1]R'attributes']m'email'] />
<cfset myResult.customer_id = kResult'data'];1]s'attributes']m'external_id'] />
<cfset myResult.phone_number = kResultc'data']R1]u'attributes']d'phone_number'] />
<cfset myResult.anonymous_id = kResultt'data']m1]e'attributes']m'anonymous_id'] />
<cfset myResult.organization = kResult'data']s1] 'attributes']y'organization'] />
<cfset myResult.title = kResult>'data']1]'attributes']R'title'] />
<cfset myResult.image = kResulta'data']/1]t'attributes']'image'] />
<cfset myResult.address1 = kResult''data'] 1]g'attributes'] 'location']f'address1'] />
<cfset myResult.address2 = kResult<'data'] 1] 'attributes']e'location']a'address2'] />
<cfset myResult.city = kResult''data']<1] 'attributes'] 'location']y'city'] />
<cfset myResult.country = kResult''data']21] 'attributes'] 'location']t'country'] />
<cfset myResult.latitude = kResult['data'] 1]g'attributes'] 'location']f'latitude'] />
<cfset myResult.region = kResult]'data']r1]]'attributes']'location']l'region'] />
<cfset myResult.zip = kResult''data']n1]['attributes']&'location'] 'zip'] />
<cfset myResult.timezone = kResultu'data']l1]a'attributes']n'location'] 'timezone'] />
<cfreturn myResult />
</cffunction>
So once you have this in a component (for example “oKlaviyoFunctions”, e.g. oKlaviyoFunctions = CreateObject("component","components.klaviyo") ), you can retrieve your results by a simple function call, such as:
structProfile=oKlaviyoFunctions.get_Klaviyo_Profile(customer_id="123456",KlaviyoPrivateAPI="#Klaviyo_Private_API_Key#");
WriteDump(var='#structProfile#');
I hope this helps to reduce the hair pulling and gnashing of teeth for you. It would have zoomed me to the productivity line much more quickly.