├── .gitignore
├── media
├── heading.PNG
└── output.PNG
├── src
├── FacebookAds16.png
├── FacebookAds20.png
├── FacebookAds24.png
├── FacebookAds32.png
├── FacebookAds40.png
├── FacebookAds48.png
├── FacebookAds64.png
├── FacebookAds80.png
├── FacebookAds.query.pq
├── FacebookAds.mproj
├── FacebookAds.pq
└── resources.resx
├── LICENSE
├── FacebookAds.sln
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | src/obj/
2 | src/bin/
3 |
--------------------------------------------------------------------------------
/media/heading.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hugoberry/FacebookAds/HEAD/media/heading.PNG
--------------------------------------------------------------------------------
/media/output.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hugoberry/FacebookAds/HEAD/media/output.PNG
--------------------------------------------------------------------------------
/src/FacebookAds16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hugoberry/FacebookAds/HEAD/src/FacebookAds16.png
--------------------------------------------------------------------------------
/src/FacebookAds20.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hugoberry/FacebookAds/HEAD/src/FacebookAds20.png
--------------------------------------------------------------------------------
/src/FacebookAds24.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hugoberry/FacebookAds/HEAD/src/FacebookAds24.png
--------------------------------------------------------------------------------
/src/FacebookAds32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hugoberry/FacebookAds/HEAD/src/FacebookAds32.png
--------------------------------------------------------------------------------
/src/FacebookAds40.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hugoberry/FacebookAds/HEAD/src/FacebookAds40.png
--------------------------------------------------------------------------------
/src/FacebookAds48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hugoberry/FacebookAds/HEAD/src/FacebookAds48.png
--------------------------------------------------------------------------------
/src/FacebookAds64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hugoberry/FacebookAds/HEAD/src/FacebookAds64.png
--------------------------------------------------------------------------------
/src/FacebookAds80.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hugoberry/FacebookAds/HEAD/src/FacebookAds80.png
--------------------------------------------------------------------------------
/src/FacebookAds.query.pq:
--------------------------------------------------------------------------------
1 | // Use this file to write queries to test your data connector
2 | let
3 | result = FacebookAds.API("/me/adaccounts",[fields="name"])[data]{0}
4 | in
5 | result
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/FacebookAds.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.26730.16
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{4DF76451-A46A-4C0B-BE03-459FAAFA07E6}") = "FacebookAds", "src\FacebookAds.mproj", "{5B722117-0B4D-4C32-93DA-300DEB8C9F30}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|x86 = Debug|x86
11 | Release|x86 = Release|x86
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {5B722117-0B4D-4C32-93DA-300DEB8C9F30}.Debug|x86.ActiveCfg = Debug|x86
15 | {5B722117-0B4D-4C32-93DA-300DEB8C9F30}.Debug|x86.Build.0 = Debug|x86
16 | {5B722117-0B4D-4C32-93DA-300DEB8C9F30}.Release|x86.ActiveCfg = Release|x86
17 | {5B722117-0B4D-4C32-93DA-300DEB8C9F30}.Release|x86.Build.0 = Release|x86
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {58508690-E0FD-4EBC-8615-69B592B9063E}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # FacebooksAds PowerBI data connector
2 | PwerBI data connector for FacevookAds
3 |
4 | 
5 |
6 | ## Quickstart
7 | This module uses the extensibility provided by [Data Connectors](https://github.com/Microsoft/DataConnectors), so in order to use it you have to:
8 | 1. Create a `[My Documents]\Microsoft Power BI Desktop\Custom Connectors` directory
9 | 2. Enable the **Custom data connectors** preview feature in Power BI Desktop (under *File | Options and settings | Custom data connectors*)
10 | 3. Copy the the *.mez file from `/build` folder into the above folder
11 | 4. Restart Power BI Desktop
12 |
13 |
14 | ## For developers
15 | In order to extend the modules
16 | 1. Install the [Power Query SDK](https://aka.ms/powerquerysdk) from the Visual Studio Marketplace
17 | 2. Edit the existing `Data Connector Project` or *.pq files
18 | 3. Build the solution
19 | The deployable *.mez files will be located in the Debug folder of each module under `/src`. The Relese configuration of the build will copy these files into the `/build` folder.
20 |
21 | # Functions
22 | For additional examples and documentation please refer to the embeded documentation of each of the functions.
23 | ## FacebookAds.Campaign
24 | A function that returns statistical insights related to the campaigns associated with connected user
25 |
26 | `FacebookAds.Campaigns()`
27 | ### Output
28 | 
29 |
30 | ## FacebookAds.API
31 | Return a function which always returns a given value.
32 |
33 | `FacebookAds.API(URI as URI.Type, params as record)`
34 |
35 | Example
36 | `FacebookAds.API("/me/adaccounts",[fields="name"])[data]{0}`
37 |
38 |
--------------------------------------------------------------------------------
/src/FacebookAds.mproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | Debug
4 | 2.0
5 |
6 |
7 | Exe
8 | MyRootNamespace
9 | MyAssemblyName
10 | False
11 | False
12 | True
13 | False
14 | True
15 | True
16 | True
17 | True
18 | False
19 | False
20 | 1000
21 | Yes
22 | FacebookAds
23 |
24 |
25 | false
26 |
27 | bin\Debug\
28 |
29 |
30 | false
31 | ..\build\
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 | Code
42 |
43 |
44 | Code
45 |
46 |
47 | Code
48 |
49 |
50 | Code
51 |
52 |
53 | Code
54 |
55 |
56 | Code
57 |
58 |
59 | Code
60 |
61 |
62 | Code
63 |
64 |
65 | Code
66 |
67 |
68 | Code
69 |
70 |
71 | Code
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
--------------------------------------------------------------------------------
/src/FacebookAds.pq:
--------------------------------------------------------------------------------
1 | // This file contains your Data Connector logic
2 | section FacebookAds;
3 |
4 | app_secret = Extension.LoadString("AppSecret");
5 | app_id = Extension.LoadString("AppId");
6 | redirectUrl = "https://preview.powerbi.com/views/oauthredirect.html";
7 | windowWidth = 720;
8 | windowHeight = 1024;
9 |
10 | [DataSource.Kind="FacebookAds", Publish="FacebookAds.Publish"]
11 | shared FacebookAds.Campaigns = (optional url as text, optional params as record) =>
12 | let
13 | key = Extension.CurrentCredential()[access_token],
14 | accountRequest = Web.Contents("https://graph.facebook.com/v2.11/me/adaccounts?"&Uri.BuildQueryString([access_token=key,fields="name"])),
15 | adaccounts = Json.Document(accountRequest)[data],
16 | out = UserToNavTabler(adaccounts)
17 |
18 | in
19 | out;
20 |
21 | [DataSource.Kind="FacebookAds"]
22 | shared FacebookAds.API = (optional url as text, optional params as record) =>
23 | let
24 | key = Extension.CurrentCredential()[access_token],
25 | allParams = if params=null then [access_token=key] else [access_token=key]¶ms,
26 | apiRequest = Web.Contents("https://graph.facebook.com/v2.11"&url&"?"&Uri.BuildQueryString(allParams)),
27 | out = Json.Document(apiRequest)
28 | in
29 | out;
30 |
31 | UserToNavTabler = (users as list) =>
32 | let
33 | navCol = {"Name","Key","Data","ItemKind", "ItemName", "IsLeaf"},
34 | navRow = List.Accumulate(users,{},(s,c)=>s&{{c[name],c[id],GetAccountCampaignsInsights(c),"Table","Table",true}} ),
35 | objects = #table(navCol,navRow),
36 | out = Table.ToNavigationTable(objects, {"Key"}, "Name", "Data", "ItemKind", "ItemName", "IsLeaf")
37 | in
38 | out;
39 |
40 | GetAccountCampaignsInsights = (adaccount) =>
41 | let
42 | key = Extension.CurrentCredential()[access_token],
43 | campaignsReq = Web.Contents("https://graph.facebook.com/v2.11/"&adaccount[id]&"/campaigns?"&Uri.BuildQueryString([access_token=key,fields="name"])),
44 | campaigns=Json.Document(campaignsReq)[data],
45 | out = List.Accumulate(campaigns,#table(null,{}),(s,c)=>s&GetCampaignInsights(c))
46 | in
47 | out;
48 |
49 | GetCampaignInsights = (campaign) =>
50 | let
51 | key = Extension.CurrentCredential()[access_token],
52 | insights = Web.Contents("https://graph.facebook.com/v2.11/"&campaign[id]&"/insights?"&Uri.BuildQueryString([access_token=key,fields="total_actions,reach,impressions,frequency,unique_clicks,spend"])),
53 | res = Json.Document(insights)[data],
54 | out = if res={} then campaign else campaign&res{0}
55 | in
56 | Table.FromRecords({out});
57 |
58 | // Data Source Kind description
59 | FacebookAds = [
60 | Authentication = [
61 |
62 | OAuth = [
63 | StartLogin = StartLogin,
64 | FinishLogin = FinishLogin,
65 | Label = Extension.LoadString("AuthenticationLabel")
66 | ]
67 | ],
68 | Label = Extension.LoadString("DataSourceLabel")
69 | ];
70 |
71 | // Data Source UI publishing description
72 | FacebookAds.Publish = [
73 | Beta = true,
74 | Category = "Other",
75 | ButtonText = { Extension.LoadString("ButtonTitle"), Extension.LoadString("ButtonHelp") },
76 | LearnMoreUrl = "https://powerbi.microsoft.com/",
77 | SourceImage = FacebookAds.Icons,
78 | SourceTypeImage = FacebookAds.Icons
79 | ];
80 |
81 | FacebookAds.Icons = [
82 | Icon16 = { Extension.Contents("FacebookAds16.png"), Extension.Contents("FacebookAds20.png"), Extension.Contents("FacebookAds24.png"), Extension.Contents("FacebookAds32.png") },
83 | Icon32 = { Extension.Contents("FacebookAds32.png"), Extension.Contents("FacebookAds40.png"), Extension.Contents("FacebookAds48.png"), Extension.Contents("FacebookAds64.png") }
84 | ];
85 |
86 | StartLogin = (resourceUrl, state, display) =>
87 | let
88 | AuthorizeUrl = "https://www.facebook.com/v2.11/dialog/oauth?" & Uri.BuildQueryString([
89 | client_id = app_id,
90 | redirect_uri = redirectUrl,
91 | scope="ads_read"])
92 | in
93 | [
94 | LoginUri = AuthorizeUrl,
95 | CallbackUri = redirectUrl,
96 | WindowHeight = windowHeight,
97 | WindowWidth = windowWidth,
98 | Context = null
99 | ];
100 |
101 | FinishLogin = (context, callbackUri, state) =>
102 | let
103 | parts = Uri.Parts(callbackUri)[Query],
104 | result = if (Record.HasFields(parts, {"error", "error_description"})) then
105 | error Error.Record(parts[error], parts[error_description], parts)
106 | else
107 | TokenMethod(parts[code])
108 | in
109 | result;
110 |
111 | TokenMethod = (code) =>
112 | let
113 | response = Web.Contents("https://graph.facebook.com/v2.11/oauth/access_token?" & Uri.BuildQueryString([
114 | client_id = app_id,
115 | redirect_uri = redirectUrl,
116 | client_secret = app_secret,
117 | code = code]),
118 | [ManualStatusHandling = {400}]),
119 | body = Json.Document(response),
120 | result = if (Record.HasFields(body, {"error", "error_description"})) then
121 | error Error.Record(body[error], body[error_description], body)
122 | else
123 | body
124 | in
125 | result;
126 |
127 | Table.ToNavigationTable = (
128 | table as table,
129 | keyColumns as list,
130 | nameColumn as text,
131 | dataColumn as text,
132 | itemKindColumn as text,
133 | itemNameColumn as text,
134 | isLeafColumn as text
135 | ) as table =>
136 | let
137 | tableType = Value.Type(table),
138 | newTableType = Type.AddTableKey(tableType, keyColumns, true) meta
139 | [
140 | NavigationTable.NameColumn = nameColumn,
141 | NavigationTable.DataColumn = dataColumn,
142 | NavigationTable.ItemKindColumn = itemKindColumn,
143 | Preview.DelayColumn = itemNameColumn,
144 | NavigationTable.IsLeafColumn = isLeafColumn
145 | ],
146 | navigationTable = Value.ReplaceType(table, newTableType)
147 | in
148 | navigationTable;
--------------------------------------------------------------------------------
/src/resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 | 2041581656054412
122 |
123 |
124 | c20db9c91968cf6fa9b551252f4ee92d
125 |
126 |
127 | FacebookOAuth
128 |
129 |
130 | Connect to FacebookAds
131 |
132 |
133 | FacebookAds
134 |
135 |
136 | FacebookAds
137 |
138 |
--------------------------------------------------------------------------------