Tuesday, November 12, 2019

Progressive Web App as Share Target on Android

I built a PWA (Progressive Web App) to trace shortened URL back to its original URL. (You can find it here.) I don’t want to copy a URL and paste it into my app. I want to use the Android’s sharesheet to send any link in Chrome straight to my app. How do I do that?

Google provides good documentation on this. We need to add a share_target section in manifest.json and then declare that our PWA can act as a share target. Most of the properties in this section can be thought of as attributes on a <form> element with the same name. For example, { "action": "/share", "method": "POST" } is like <form action="/share" method="POST">.

params subsection let us change parameter names if we already have a convension of naming search parameters in GET requests or form fields in POST requests. Otherwise, we can keep them in their original names. One caveat is Android doesn’t use url parameter so when sharing a URL it comes through the text parameter. In my app I need to coalesce these two parameters to get the input from the user.

Is there more? Yes! Twitter makes a great PWA and we can check their manifest.json. Here’s the beautified version of the share_target section:

"share_target": {
  "action": "compose/tweet",
  "enctype": "multipart/form-data",
  "method": "POST",
  "params": {
    "title": "title",
    "text": "text",
    "url": "url",
    "files": [
      {
        "name": "externalMedia",
        "accept": [
          "image/jpeg",
          "image/png",
          "image/gif",
          "video/quicktime",
          "video/mp4"
        ]
      }
    ]
  }
}

It has a files subsection under the params section. This is part of the Web Share Target Level 2. We can accept files from sharesheet and we can assign a file to different parameter name based on MIME type or file extension. My app doesn’t need this capability but it’s good to know what’s possible.

If you like my post, you can subscribe through email or RSS/Atom. That makes sure you won’t miss my future posts.

Wednesday, November 06, 2019

Batch Sending Email with Attachments through AppleScript

I want to learn a little bit of AppleScript. I need to help a friend send out emails to welcome new students to the school. The requirements are:

  1. addressing each recipient by their name in email content;
  2. attaching the same file in all emails.

After some research and tinkering I have a script to send emails:

theRecipients is the list of recipient names and email addresses. This is for requirement #1. theAttachment isn’t hardcoded to any file path. It will prompt and let me choose a file when I run the AppleScript.

The trickiest part is the delay 1. Without this line, emails will be sent without the attachment. It’s a hack to make sure each email has the attachment. I don’t know why it works and I can’t find an explanation online.

After building this AppleScript, I learn that Google App Script is another great way to automate sending emails through Gmail (or GSuite). I will learn App Script and write a post about that next time. If you like this kind of posts, you can subscribe through email or RSS/Atom.

Tuesday, September 24, 2019

MailChimp Popup Dialog on Click

Problem

MailChimp provides sign-up form as pop-up dialog, but has limited options for when to trigger it. Available triggers are like “immediately after the page is open”, “when the user scrolls to the bottom of the page”, etc. I want to trigger the dialog when a reader clicks the sign-up link on my blog. Instead of navigating to the sign-up page, I want to open the dialog and speed up the experience. I hope this can improve subscription rate.

Solution

MailChimp provides an HTML snippet for the pop-up dialog. It contains two <script> tags. I left the first one untouched and modified the second one. Read the code below for reference:

In the first <script> tag, I did nothing. In the second <script> tag, I wrapped the original JavaScript in a function called displayDialog, which will be called in the sign-up link’s click event. I added a third <script> tag to search for sign-up links in the page and add the click event handler.

Within displayDialog function, I not only call the original code in the second <script> tag but also delete two cookies before that. That’s because MailChimp set one of these cookies when a user dismisses the dialog or subscribes through the dialog. The presence of one of the cookies will prevent the dialog from opening again. This behavior makes sense when using MailChimp’s automatic triggers – a user shouldn’t see a dialog again after either dismissing or subscribing. It doesn’t make sense when the trigger is user clicking a link because it’s a clear intention to open the dialog. (If you want to reuse my code, remember to replace window.dojoRequire(...) with the code from your own MailChimp campaign.)

The third <script> tag is customized for my own blog. It looks for any link that points to the sign-up page and add the click event handler. The event handler calls displayDialog to trigger the dialog and then cancels the browser’s navigation to the sign-up page.

If you want to test this feature, make sure you open this post from my blog and click this link to subscribe. It should open the sign-up dialog instead of the sign-up page. If you like this post, remember to put in your email and subscribe!

Wednesday, August 28, 2019

Is Targeted Ads Price Discrimination?

If you use a service for free but you need to see ads targeting towards you, how much do you actually pay? I didn’t think about this before I used Google Contributor a few years ago. Now I think I pay the whatever the price advertisers pay to show me the ads, but then the advertisers subsidize me fully to get me to see their ads.

The concept of Google Contributor is very simple. You can understand it if you ever purchased targeted ads online. You set up a budget between $2 and $15 per month. You use that budget to buy ads targeting a single person – yourself. You compete against any advertisers that happen to target you. Every time when you are supposed to see an ad, the bidding process happens between you and other advertisers. If you win, you see a message saying “thank you for being a contributor” in the place where the ad should be displayed. If you lose, you see the ad from the winning advertiser, just like if you were not using Google Contributor.

I would imagine I win in every case so I never see any ads. The cost I pay for that is the price I actually pay for using the “free” service. When I don’t win or when I don’t use Google Contributor altogether, it’s advertisers subsidizing me but I have to see their ads, but it’s still the same price.

It’s interesting that different user pays different price. It’s like price discrimination. If you are worth more in the eyes of advertisers, you pay more. If your impression is worth less, you pay less. It’s easy to guess that an average user in the US would pay more than an average user in India.

If we apply similar price discrimination to a subscription based service (e.g. Microsoft Office 365, which is cheaper in China), we need to use IP check or other methods to prevent customers in a higher price region from purchasing from a lower price region. There’s no such need when the service is paid by targeted ads. A user in the US can’t pretend to be in India and then “pay” less by seeing lower cost ads. It’s also not in the US user’s interest to do so, because ads targeting an Indian user is less relevant and doesn’t improve experience.

In conclusion, I think targeted ads is an effective form of price discrimination. What do you think? (Feel free to comment after the post.)