Introduction
So my mission was to add simple code to my VB.NET website (can be easilly converted to c# using a converter), to subscribe customers to a newsletter, via a MailChimp list with 3 sub-groups (can be on one or many groups), and update the same entry if user changed details, or needed adding to another MailChimp group. Then let MailChimp automation take over the process of sending the e-mail automatically. A simple task, I thought. Wow, was I wrong!
So the guys and gals at MailChimp have done an excellent job of implementing an API to do almost anything, to lists, groups, automation, etc. but I would say that 98% requirements are simple as mine, but in order to achieve my objective, we have to know so much about JSON, GET and POST operation with authorization, etc..
Background
So I currently have 3 MailChimp lists:
One was for testing called “Test
” which had no groups.
Standard fields:
Then I had two more which have the same field names but different groups. We are going to Use “Test
” and “List Sage
” for examples.
“List Sage
” structure:
Implementation
Firstly, I read the MailChimp API, which has no documentation for C# or VB.NET, then I looked at the two API wrappers available. Both required an install into .NET, which I was reluctant to do as either I would have to do it on my web server or remember to do it when I change development machine in the future. Also reading the documentation all over again seemed too complicated.
So my objective required:
- Getting my head around the fact Groups are called “Interests” in the API.
- Get the IDs needed to update a List, with a groups and group values.
- Implement function to
GET
data from the MailChimp API, with basic authentication.
- Implement function to
POST
data to the API, with basic authentication. This took some time as I got a lot of {"The remote server returned an error: (401) Unauthorized."} until I worked out how to do it. This seems to be a common problem from what I read.
- Having got the code to add customers to the list, to update entries on a list, you have to do a different call. This means you have to first check whether the customer is on the list, if so to
PUT
, to update entry.
- When updating the contact don't change the value'status' as they may have opted out of the list.
Using the Code
Now I’m a simple guy, as you will see from my code which I could spend more days refining but don’t have the time to spend for little return. Being self-employed and an extensive job list. Time is money!
The class exposes two simple functions:
Function getListIDandGroupsAndWriteToFile() As String
Which returns all the list IDs and Groups IDs in the account. You only need to call this once or whenever you make changes to groups. These IDs can be stored in your own code or database.
Function addSubscriber(ListID$, email$, fieldList$, groupList$) As Boolean
Add or update entry on list, identified by email. See examples below.
It also exposes a function to get member details if alread on list, but not generally needed.
Function getMemberIfAlreayExists(ListID$, email$, response$) As String
Examples
First, we call getListIDandGroupsAndWriteToFile()
, which I logged to a file, and gave:
List ID:44b9dccea3 - 'Test' - members 4
List ID:9b2e63f0b9 - 'List Sage' - members 4
Group ID:5a84f8f68e - 'Interests'
Group Value ID:407da9f47d - 'Sage One' - members 0
Group Value ID:05086211ba - 'Sage 50' - members 4
Group Value ID:2ba200b991 - 'Sage 200' - members 1
List ID:e1a0e32d08 - 'List Exchequer' - members 3
Group ID:62ddcc8bf3 - 'Interest'
Group Value ID:68b98284d3 - 'PostTrans' - members 3
Group Value ID:a940bf543c - 'PostTrans XML Gateway' - members 0
Group Value ID:b9d4006df3 - 'All Other' - members 3
Now we have the IDs, which we only have to retrieve once, we can add subscriber easily:
Add/Update to list - 'Test' SIMPLE
Dim mailchimp As New ZmailChimp
Dim ListId$ = "44b9dccea3" Dim email$ = "samsmith17@anymail.com"
Dim fieldListOnAdd = "FNAME,Sam,LNAME,Smith"
Dim fieldListOnUpdate = "FNAME,Sam,LNAME,Smith"
Dim groupList = ""
With mailchimp
.API$ = "46cMailChimpAPIKeyd1de-us14" .dataCenter$ = "us14" .password$ = "Password!"
MsgBox(.addSubscriber(ListId$, email, fieldListOnAdd, fieldListOnUpdate, groupList))
End With
mailchimp = Nothing
In my application, when adding a subscriber I wanted to set the value of field, but not on updates. Hence the need for a seperate file list for updates.
Add/Update to list - 'List Sage' with groups
1 Group
Dim mailchimp As New ZmailChimp
Dim ListId$ = "9b2e63f0b9" Dim email$ = "samsmith20@anymail.com"
Dim fieldListOnAdd = "FNAME,Sam,LNAME,Smith,MTYPE,User,MID,631637"
Dim fieldListOnUpdate = "FNAME,Sam,LNAME,Smith,MID,631637" Dim groupList = "407da9f47d,05086211ba"
With mailchimp
.API$ = "46cMailChimpAPIKeyd1de-us14" .dataCenter$ = "us14" .password$ = "Password!"
MsgBox(.addSubscriber(ListId$, email, fieldListOnAdd, fieldListOnUpdate, groupList))
End With
mailchimp = Nothing
where:
FNAME = First Name
LNAME = Surname
MTYPE = Field added to store a type of user
MID = UserID in my system
2 Groups
Dim mailchimp As New ZmailChimp
Dim ListId$ = "9b2e63f0b9" Dim email$ = "samsmith19@anymail.com"
Dim fieldListOnAdd = "FNAME,Sam,LNAME,Smith,MTYPE,User,MID,631637"
Dim fieldListOnUpdate = "FNAME,Sam,LNAME,Smith,MID,631637" Dim groupList = "407da9f47d"
Dim groupList = "Interests,407da9f47d,05086211ba"
With mailchimp
.API$ = "46cMailChimpAPIKeyd1de-us14" .dataCenter$ = "us14" .password$ = "Password!"
MsgBox(.addSubscriber(ListId$, email, fieldListOnAdd, fieldListOnUpdate, groupList))
End With
mailchimp = Nothing
Simple. Once the entry has been added to the Groups/List, then MailChimp automation can take over to schedule the sending of mail, etc. which is very powerful.
Impact on your system
I actually wrote another class to store ListId,email,fieldListOnAdd,fieldListOnUpdate,groupList in a table, then process the contents of the table every hour. Thus the MailChimp subscribe process had no impact on the response of the sign up and billing process which it was added too.
Here is the code to give you some idea:
Imports Microsoft.VisualBasic
Imports System.Data.SqlClient
Public Class zMailChimpTop
Function addSubscriber(Server As Object, ListID$, email$, McFieldListADD$, McFieldListUPDATE$, groupList$, Optional MCAccID& = 1) As Boolean
Dim SQL$ = "", ErrorDesc$ = ""
addSubscriber = False
SQL = "INSERT INTO RegMailChimpProcess (MCAccID,McDate,McListID,McEmail,McFieldListUPDATE,McFieldListADD,McGroupList )"
SQL += " SELECT " & MCAccID & " as expr1"
SQL += ", " & DB.QueryDate(Now(), True) & " as expr2a"
SQL += ", " & DB.CleanTextForSQL(ListID, 20) & " as expr3"
SQL += ", " & DB.CleanTextForSQL(email, 200) & " as expr4"
SQL += ", " & DB.CleanTextForSQL(McFieldListUPDATE, 400) & " as expr5"
SQL += ", " & DB.CleanTextForSQL(McFieldListADD, 400) & " as expr6"
SQL += ", " & DB.CleanTextForSQL(groupList, 200) & " as expr7;"
If DB.ExecuteSQL(SQL, ErrorDesc) = 0 Then
logError(Server, "Error SQL:Insert Company", SQL & " - " & ErrorDesc)
Else
Return True
End If
End Function
Sub processUpdate(Server As Object)
Dim SQL$ = ""
Dim totalToPay# = 0, TotalOwed# = 0
Dim DB As New zzDatabaseStuff(Globalv.DBConnectionSupportProg2)
SQL = "SELECT RegMailChimpProcess.* from RegMailChimpProcess order by McID; "
Dim DBConnection As SqlConnection
DBConnection = New SqlConnection(Globalv.DBConnectionSupportProg2)
Try
DBConnection.Open()
Dim cmd As New SqlCommand(SQL, DBConnection)
Dim dr As SqlDataReader = cmd.ExecuteReader()
Do While dr.Read
Dim mailchimp As New ZmailChimp
Dim ListId$ = dr.Item("McListID") Dim email$ = dr.Item("McEmail") Dim McFieldListUPDATE = dr.Item("McFieldListUPDATE") Dim McFieldListADD = dr.Item("McFieldListADD") Dim groupList = ""
If Not IsDBNull(dr.Item("McGroupList")) Then
groupList = dr.Item("McGroupList")
End If
With mailchimp
.API$ = "46c9 MailChimp API key d1de-us14" .dataCenter$ = "us14" .password$ = "Your Password!"
If Not .addSubscriber(ListId$, email, McFieldListADD, McFieldListUPDATE, groupList) Then
logError(Server, "zMailChimpTop:Failed to update ", email & " - ")
Else
SQL = "DELETE [RegMailChimpProcess] FROM [RegMailChimpProcess] where McID=" & dr.Item("McID") & ";"
Dim errorDesc$ = ""
DB.ExecuteSQL(SQL, errorDesc$)
End If
End With
mailchimp = Nothing
Loop
dr.Close()
Finally
DBConnection.Close()
End Try
End Sub
End Class
Some of my library functions are missing, but it gives you the idea.
SQL to create Table
USE [supportprog2]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[RegMailChimpProcess](
[McID] [int] IDENTITY(1,1) NOT NULL,
[MCAccID] [int] NULL,
[McDate] [datetime] NULL,
[McListID] [varchar](20) NULL,
[McEmail] [varchar](200) NULL,
[McFieldListADD] [varchar](400) NULL,
[McGroupList] [varchar](200) NULL,
[McFieldListUPDATE] [varchar](400) NULL,
CONSTRAINT [PK_RegMailChimpProcess] PRIMARY KEY CLUSTERED
(
[McID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
Code Download
I’m sure I will get loads of comments about the crudeness of this implementation, and yes, it is a bit crude, but I didn’t want to load any third party objects or code.
Download Class ZmailChimp.zip
This could easily be converted to c# using a Vb.net to c# converter, easily found using goole.
Let me know if it was help to you :-)
History
- 17th October, 2016: Initial version