Article

Creating a Content Blocker

Create a Content Blocker for Safari in Xcode.

Overview

Content Blockers are app extensions that you build using Xcode. They indicate to Safari a set of rules to use to block content in the browser window. Blocking behaviors include hiding elements, blocking loads, and stripping cookies from Safari requests.

You use a containing app to contain and deliver a Content Blocker on the App Store. The containing app defines the context provided to the extension and initiates the extension life cycle by sending a request in response to a user action.

When the Content Blocker is launched, it communicates with its containing app through a set of shared resources, and it communicates directly with Safari.

Image showing a Content Blocker communicating with various resources.

Apps tell Safari in advance what kinds of content to block. Because Safari doesn't have to consult with the app during loading, and because Xcode compiles Content Blockers into bytecode, this model runs efficiently. Additionally, Content Blockers have no knowledge of users' history or the websites they visit.

Add the Extension Target to Your Containing App

Choose File > New > Target and select Content Blocker Extension. Give your Content Blocker a name.

Image showing the Content Blocker Extension target selected.

Add Behaviors to Your Content Blocker

In your Xcode project, open the folder with the same title as your Content Blocker. This folder contains the action request handler and a JSON file, along with a property list file and an entitlements file. Open the blockerList.json file.

In the JSON file, write rules to define content-blocking behaviors. Each rule is a JSON object containing action and trigger dictionaries. The action tells Safari what to do when the trigger is matched. The trigger tells Safari when to perform the corresponding action. Content Blockers are JSON arrays of these rules.

[
    {
        "trigger": {
            ...
        },
        "action": {
            ...
        }
    },
    {
        "trigger": {
            ...
        },
        "action": {
            ...
        }
    }
]

Add Triggers to Your Content Blocker

A trigger dictionary must include a url-filter key, which specifies a pattern to match the URL against. The remaining keys are optional and modify the behavior of the trigger. For example, you can limit the trigger to specific domains or have it not apply when a match is found on a specific domain.

For example, to write a trigger for image and stylesheet resources found on any domain except those specified:

"trigger": {
        "url-filter": ".*",
        "resource-type": ["image", "style-sheet"],
        "unless-domain": ["your-content-server.com", "trusted-content-server.com"]
}

Capture URLs by Pattern

In url-filter, match more than just a specific URL, using regular expressions:

Syntax

Description

.*

Matches all strings with a dot appearing zero or more times. Use this syntax to match every URL.

.

Matches any character.

\.

Explicitly matches the dot character.

[a-b]

Matches a range of alphabetic characters.

(abc)

Matches groups of the specified characters.

+

Matches the preceding term one or more times.

*

Matches the preceding character zero or more times.

?

Matches the preceding character zero or one time.

Use Trigger Fields to Define Patterns

There are many valid trigger fields you can use to define patterns:

Trigger

Description

url-filter-is-case-sensitive

A Boolean value. The default value is false.

if-domain

An array of strings matched to a URL's domain; limits action to a list of specific domains. Values must be lowercase ASCII, or punycode for non-ASCII. Add * in front to match domain and subdomains. Can't be used with unless-domain.

unless-domain

An array of strings matched to a URL's domain; acts on any site except domains in a provided list. Values must be lowercase ASCII, or punycode for non-ASCII. Add * in front to match domain and subdomains. Can't be used with if-domain.

resource-type

An array of strings representing the resource types (how the browser intends to use the resource) that the rule should match. If not specified, the rule matches all resource types. Valid values: document, image, style-sheet, script, font, raw (Any untyped load), svg-document, media, popup.

load-type

An array of strings that can include one of two mutually exclusive values. If not specified, the rule matches all load types. first-party is triggered only if the resource has the same scheme, domain, and port as the main page resource. third-party is triggered if the resource is not from the same domain as the main page resource.

if-top-url

An array of strings matched to the entire main document URL; limits the action to a specific list of URL patterns. Values must be lowercase ASCII, or punycode for non-ASCII. Can't be used with unless-top-url.

unless-top-url

An array of strings matched to the entire main document URL; acts on any site except URL patterns in provided list. Values must be lowercase ASCII, or punycode for non-ASCII. Can't be used with if-top-url.

Add Actions to Your Content Blocker

When a trigger matches a resource, the browser queues the associated action for execution. Safari evaluates all the triggers, it executes the actions in order. When a domain matches a trigger, all rules after the triggered rule that specify the same action are skipped.

Group the rules with similar actions together to improve performance. For example, first specify rules that block content loading, followed by rules that block cookies. The trigger evaluation continues at the first rule that specifies a different action.

There are only two valid fields for actions: type and selector. An action type is required. If the type is css-display-none, a selector is required as well; otherwise the selector is optional.

For example, you can specify the follow type and selector:

"action": {
        "type": "css-display-none",
        "selector": "#newsletter, :matches(.main-page, .article) .news-overlay"
}

Select Values for the Type Field

Syntax

Description

block

Stops loading of the resource. If the resource was cached, the cache is ignored.

block-cookies

Strips cookies from the header before sending to the server. Only cookies otherwise acceptable to Safari's privacy policy can be blocked. Combining with ignore-previous-rules doesn't override the browser’s privacy settings.

css-display-none

Hides elements of the page based on a CSS selector. A selector field contains the selector list. Any matching element has its display property set to none, which hides it.

ignore-previous-rules

Ignores previously triggered actions.

make-https

Changes a URL from http to https. URLs with a specified (nondefault) port and links using other protocols are unaffected.

For the selector field, specify a string that defines a selector list. This value is required when the action type is css-display-none. If it's not, the selector field is ignored by Safari. Use CSS identifiers as the individual selector values, separated by commas. Safari and WebKit supports all of its CSS selectors for Safari content-blocking rules.

See Also

Content Blockers

class SFContentBlockerManager

A class used by your app to interact with a content blocker extension.

class SFContentBlockerState

The state of a content blocker extension.

let SFContentBlockerErrorDomain: String

The domain for content blocker errors.

Deprecated
enum SFContentBlockerErrorCode

Messages that describe a content blocker error.

Deprecated