{"id":68,"date":"2018-05-16T15:19:25","date_gmt":"2018-05-16T15:19:25","guid":{"rendered":"http:\/\/www.gaminggarrison.com\/Site\/?p=68"},"modified":"2018-05-16T16:14:43","modified_gmt":"2018-05-16T16:14:43","slug":"unity-and-mailchimp-for-in-event-mailing-list-capture","status":"publish","type":"post","link":"https:\/\/www.gaminggarrison.com\/Site\/unity-and-mailchimp-for-in-event-mailing-list-capture\/","title":{"rendered":"Unity and MailChimp (for in-event mailing list capture)"},"content":{"rendered":"<p>I&#8217;m going to show off <a href=\"http:\/\/www.gaminggarrison.com\/press\/midithecat\/index.html\">Midi The Cat<\/a> at the Norwich Gaming Festival in a couple of weeks, and one thing I wanted to have is a form after the victory screen for players to sign up to the mailing list.<br \/>\nI had my Unity UI for the submission, but wanted to be GDPR compliant by doing the double-opt-in stuff where it sends a confirmation email and that jazz.<\/p>\n<p>After some research, it seemed a good solution would be to use MailChimp &#8211; a web service for storing email contacts and sending out bulk emails.<\/p>\n<p>This is when the fun began.<\/p>\n<p>After making a MailChimp form that matched my data fields (email and feedback string), I wanted to push to it from Unity.<br \/>\nMy initial approach was to use a push request to the form page directly, and with some wrangling had something that looked like this:<\/p>\n<p>[csharp]<br \/>\nm_form = new WWWForm();<br \/>\nm_form.AddField(&quot;MERGE0&quot;, m_emailInput.text);<br \/>\nm_form.AddField(&quot;MERGE1&quot;, m_feedbackInput.text);<\/p>\n<p>\/\/ Some extra hidden fields that I apparently need to fill in my form?<br \/>\nm_form.AddField(&quot;u&quot;, &quot;1f271a9e997836765ea218377&quot;);<br \/>\nm_form.AddField(&quot;id&quot;, &quot;bef723ffb7&quot;);<\/p>\n<p>using (var w = UnityWebRequest.Post(&quot;https:\/\/gaminggarrison.us18.list-manage.com\/subscribe\/post?u=1f271a9e997836765ea218377&amp;amp;id=bef723ffb7&quot;, m_form))<br \/>\n{<br \/>\n\tyield return w.SendWebRequest();<br \/>\n\tif (w.isNetworkError || w.isHttpError)<br \/>\n\t{<br \/>\n\t\tDebug.LogError(w.error);<br \/>\n\t\tOnFailure();<br \/>\n\t}<br \/>\n\telse<br \/>\n\t{<br \/>\n\t\tDebug.Log(&quot;Submission successful!&quot;);<br \/>\n\t\tOnSuccess();<br \/>\n\t}<br \/>\n}<br \/>\n[\/csharp]<\/p>\n<p>Now apart from finding out you needed to fill hidden form fields, this looked reasonable.<br \/>\nUnfortunately I was hitting this error: <a href=\"https:\/\/forum.unity.com\/threads\/www-calls-return-http-code-411-content-length-required.509906\/\">411 Content Length Required<\/a><br \/>\nNow, I can&#8217;t easily upgrade my Unity, because I tried 2017.4 and it horribly broke my UI (randomly positioning it offscreen &#8211; probably due to some uninitialised positions when my script was running, but I didn&#8217;t want to put workarounds everywhere).<br \/>\nSo after some more googling, I found out that you needed the magic work-around line:<br \/>\n[csharp]<br \/>\n\tw.chunkedTransfer = false;<br \/>\n[\/csharp]<br \/>\nbefore you SendWebRequest();<br \/>\nand everything will be fine.  Well, yes, it seemed fine &#8211; I actually managed to submit a test email, and get the opt-in email and everything.<br \/>\nUnfortunately, testing a second time came out with nothing, and a third time&#8230;<\/p>\n<p>I tried using the form directly, yes it works there &#8211; but it popped up an &#8220;Are you Human&#8221; captcha, so that&#8217;s probably it isn&#8217;t it &#8211; the captcha was breaking my form submission.<br \/>\nI went through the settings in MailChimp, and I had the re-captcha turned off, but I&#8217;m guessing they have something on at all times, so this wasn&#8217;t going to pan out.<\/p>\n<p><strong><br \/>\nBack to the Drawing Board<br \/>\n<\/strong><br \/>\nNow I was vaguely aware that MailChimp had a RESTful API (which is v3 ATM), so I figured &#8211; I&#8217;ll just use that so I won&#8217;t be suckered by surprise captchas.<br \/>\nThe first thing you&#8217;ll find if you google this stuff is huge github repos like <a href=\"https:\/\/github.com\/brandonseydel\/MailChimp.Net\">MailChimp.net<\/a>, but I didn&#8217;t want to muddy my whole game just for a simple web request, and &#8216;fortunately&#8217; I managed to find a simple and promising looking example: <a href=\"https:\/\/github.com\/fiftytwo\/MailChimpSubscriber\">https:\/\/github.com\/fiftytwo\/MailChimpSubscriber<\/a><\/p>\n<p>Of course, trying that just gave me failed post responses, with &#8220;generic http error&#8221; messages &#8211; how useful.  (I found out later that if your API actually returns nice error data, as MailChimp does, request.downloadHandler.text is MUCH more useful than request.error)<br \/>\nMaybe it was breaking because it was using Unity&#8217;s deprecated WWW API?  Thus I converted it to use UnityWebRequest.  Still no luck.  I was banging my head against the wall at this point, blaming everything from the auth to the data json, so I went looking for some web-request debugging tools, first finding <a href=\"https:\/\/github.com\/wiztools\/rest-client\">WizTools Rest Client<\/a> and then the much more modern (and helpful) <a href=\"https:\/\/www.getpostman.com\/\">Postman<\/a>.<br \/>\nNow I could test my post request, with the auth header and json body and find the error &#8211; when of course, it <strong>worked first time<\/strong>.<\/p>\n<p>I figured it had to be my code somehow, and I spent quite some time double checking, Debug.Log&#8217;ging, and generally going over my references to see if I was missing something.<br \/>\nAt this point I&#8217;m questioning whether UnityWebRequest even sends my data and doesn&#8217;t just throw random garbage at the window, so of course, I try building the UTF8 byte array manually and&#8230;<br \/>\nIt works!  I&#8217;m saved!  It only took me the better part of a day to solve a one-liner problem!   &#8230;but why didn&#8217;t it work before??<br \/>\nTurns out, yes, I&#8217;d found a bug in Unity again :-\/<br \/>\nSpecifically, <a href=\"https:\/\/forum.unity.com\/threads\/unitywebrequest-post-sends-strings-with-escaped-characters.507472\/\">this bug<\/a>.<\/p>\n<p>For me, this meant that this call on my post request<br \/>\n[csharp]<br \/>\n\twww.SetRequestHeader(&quot;Content-Type&quot;, &quot;text\/plain&quot;);<br \/>\n[\/csharp]<br \/>\nwas actually doing nothing (well, maybe it sets the header, but the post data doesn&#8217;t get packed as UTF8 &#8211; though the <a href=\"https:\/\/docs.unity3d.com\/ScriptReference\/Networking.UnityWebRequest.Post.html\">documentation <\/a>implies it).<\/p>\n<p>so now, instead I have:<br \/>\n[csharp]<br \/>\n\twww.uploadHandler = new UploadHandlerRaw(System.Text.Encoding.UTF8.GetBytes(data));<br \/>\n\twww.uploadHandler.contentType = &quot;text\/plain&quot;;<br \/>\n\twww.SetRequestHeader(&quot;Authorization&quot;, &quot;apikey &quot; + _apiKey);<br \/>\n\t\/\/www.SetRequestHeader(&quot;Content-Type&quot;, &quot;text\/plain&quot;); \/\/ Doesn&#8217;t work due to bug in 2017.3 :@<br \/>\n[\/csharp]<\/p>\n<p>and of course the<br \/>\n[csharp]<br \/>\n\twww.chunkedTransfer = false;<br \/>\n[\/csharp]<\/p>\n<p>So that&#8217;s it folks, remember to check that your simple library call is actually doing anything near what you expect it to do.  Maybe you&#8217;ll even save time by reading Unity&#8217;s bug reports BEFORE checking your own code. \ud83d\ude09<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I&#8217;m going to show off Midi The Cat at the Norwich Gaming Festival in a couple of weeks, and one thing I wanted to have is a form after the victory screen for players to sign up to the mailing list. I had my Unity UI for the submission, but wanted to be GDPR compliant&#8230;<\/p>\n<p class=\"more-link\"><a href=\"https:\/\/www.gaminggarrison.com\/Site\/unity-and-mailchimp-for-in-event-mailing-list-capture\/\" class=\"themebutton3\">Read More<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[],"class_list":["post-68","post","type-post","status-publish","format-standard","hentry","category-coding"],"_links":{"self":[{"href":"https:\/\/www.gaminggarrison.com\/Site\/wp-json\/wp\/v2\/posts\/68","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.gaminggarrison.com\/Site\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.gaminggarrison.com\/Site\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.gaminggarrison.com\/Site\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.gaminggarrison.com\/Site\/wp-json\/wp\/v2\/comments?post=68"}],"version-history":[{"count":20,"href":"https:\/\/www.gaminggarrison.com\/Site\/wp-json\/wp\/v2\/posts\/68\/revisions"}],"predecessor-version":[{"id":89,"href":"https:\/\/www.gaminggarrison.com\/Site\/wp-json\/wp\/v2\/posts\/68\/revisions\/89"}],"wp:attachment":[{"href":"https:\/\/www.gaminggarrison.com\/Site\/wp-json\/wp\/v2\/media?parent=68"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.gaminggarrison.com\/Site\/wp-json\/wp\/v2\/categories?post=68"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.gaminggarrison.com\/Site\/wp-json\/wp\/v2\/tags?post=68"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}